about summary refs log tree commit diff
path: root/app/assets/javascripts
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts')
-rw-r--r--app/assets/javascripts/application.js4
-rw-r--r--app/assets/javascripts/channels/timeline.js13
-rw-r--r--app/assets/javascripts/components.js9
-rw-r--r--app/assets/javascripts/components/.gitkeep0
-rw-r--r--app/assets/javascripts/components/actions/statuses.jsx18
-rw-r--r--app/assets/javascripts/components/components/column.jsx19
-rw-r--r--app/assets/javascripts/components/components/column_header.jsx15
-rw-r--r--app/assets/javascripts/components/components/columns_area.jsx15
-rw-r--r--app/assets/javascripts/components/components/frontend.jsx16
-rw-r--r--app/assets/javascripts/components/components/nav_bar.jsx8
-rw-r--r--app/assets/javascripts/components/components/status.jsx19
-rw-r--r--app/assets/javascripts/components/components/status_list.jsx22
-rw-r--r--app/assets/javascripts/components/containers/root.jsx40
-rw-r--r--app/assets/javascripts/components/containers/status_list_container.jsx10
-rw-r--r--app/assets/javascripts/components/reducers/index.jsx6
-rw-r--r--app/assets/javascripts/components/reducers/statuses.jsx17
-rw-r--r--app/assets/javascripts/components/store/configureStore.jsx6
17 files changed, 223 insertions, 14 deletions
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 646c5aba4..b9d77b07f 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -12,4 +12,6 @@
 //
 //= require jquery
 //= require jquery_ujs
-//= require_tree .
+//= require components
+//= require cable
+//= require mastodon-logo
diff --git a/app/assets/javascripts/channels/timeline.js b/app/assets/javascripts/channels/timeline.js
deleted file mode 100644
index ca7c50d12..000000000
--- a/app/assets/javascripts/channels/timeline.js
+++ /dev/null
@@ -1,13 +0,0 @@
-App.timeline = App.cable.subscriptions.create("TimelineChannel", {
-  connected: function() {
-    console.log('Connected');
-  },
-
-  disconnected: function() {
-    console.log('Disconnected');
-  },
-
-  received: function(data) {
-    console.log(JSON.parse(data.message));
-  }
-});
diff --git a/app/assets/javascripts/components.js b/app/assets/javascripts/components.js
new file mode 100644
index 000000000..d4d9b97e4
--- /dev/null
+++ b/app/assets/javascripts/components.js
@@ -0,0 +1,9 @@
+//= require_self
+//= require react_ujs
+
+window.React    = require('react');
+window.ReactDOM = require('react-dom');
+
+//= require_tree ./components
+
+window.Root = require('./components/containers/root');
diff --git a/app/assets/javascripts/components/.gitkeep b/app/assets/javascripts/components/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/app/assets/javascripts/components/.gitkeep
diff --git a/app/assets/javascripts/components/actions/statuses.jsx b/app/assets/javascripts/components/actions/statuses.jsx
new file mode 100644
index 000000000..21821b8ba
--- /dev/null
+++ b/app/assets/javascripts/components/actions/statuses.jsx
@@ -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
+  };
+}
diff --git a/app/assets/javascripts/components/components/column.jsx b/app/assets/javascripts/components/components/column.jsx
new file mode 100644
index 000000000..c585b6b0b
--- /dev/null
+++ b/app/assets/javascripts/components/components/column.jsx
@@ -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;
diff --git a/app/assets/javascripts/components/components/column_header.jsx b/app/assets/javascripts/components/components/column_header.jsx
new file mode 100644
index 000000000..e2f7d7c1c
--- /dev/null
+++ b/app/assets/javascripts/components/components/column_header.jsx
@@ -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;
diff --git a/app/assets/javascripts/components/components/columns_area.jsx b/app/assets/javascripts/components/components/columns_area.jsx
new file mode 100644
index 000000000..1c46f722d
--- /dev/null
+++ b/app/assets/javascripts/components/components/columns_area.jsx
@@ -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;
diff --git a/app/assets/javascripts/components/components/frontend.jsx b/app/assets/javascripts/components/components/frontend.jsx
new file mode 100644
index 000000000..6f9c46fa9
--- /dev/null
+++ b/app/assets/javascripts/components/components/frontend.jsx
@@ -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;
diff --git a/app/assets/javascripts/components/components/nav_bar.jsx b/app/assets/javascripts/components/components/nav_bar.jsx
new file mode 100644
index 000000000..1ece3cc34
--- /dev/null
+++ b/app/assets/javascripts/components/components/nav_bar.jsx
@@ -0,0 +1,8 @@
+const NavBar = React.createClass({
+
+  render: function() {
+    return <div style={{ background: '#2f3441', width: '60px', margin: '10px', marginRight: '0' }} />;
+  }
+});
+
+export default NavBar;
diff --git a/app/assets/javascripts/components/components/status.jsx b/app/assets/javascripts/components/components/status.jsx
new file mode 100644
index 000000000..9bbb02077
--- /dev/null
+++ b/app/assets/javascripts/components/components/status.jsx
@@ -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;
diff --git a/app/assets/javascripts/components/components/status_list.jsx b/app/assets/javascripts/components/components/status_list.jsx
new file mode 100644
index 000000000..c986c773b
--- /dev/null
+++ b/app/assets/javascripts/components/components/status_list.jsx
@@ -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;
diff --git a/app/assets/javascripts/components/containers/root.jsx b/app/assets/javascripts/components/containers/root.jsx
new file mode 100644
index 000000000..7da984d89
--- /dev/null
+++ b/app/assets/javascripts/components/containers/root.jsx
@@ -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;
diff --git a/app/assets/javascripts/components/containers/status_list_container.jsx b/app/assets/javascripts/components/containers/status_list_container.jsx
new file mode 100644
index 000000000..c2e55db66
--- /dev/null
+++ b/app/assets/javascripts/components/containers/status_list_container.jsx
@@ -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);
diff --git a/app/assets/javascripts/components/reducers/index.jsx b/app/assets/javascripts/components/reducers/index.jsx
new file mode 100644
index 000000000..c7e858f38
--- /dev/null
+++ b/app/assets/javascripts/components/reducers/index.jsx
@@ -0,0 +1,6 @@
+import { combineReducers } from 'redux-immutable';
+import statuses            from './statuses';
+
+export default combineReducers({
+  statuses
+});
diff --git a/app/assets/javascripts/components/reducers/statuses.jsx b/app/assets/javascripts/components/reducers/statuses.jsx
new file mode 100644
index 000000000..d69d66328
--- /dev/null
+++ b/app/assets/javascripts/components/reducers/statuses.jsx
@@ -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;
+  }
+}
diff --git a/app/assets/javascripts/components/store/configureStore.jsx b/app/assets/javascripts/components/store/configureStore.jsx
new file mode 100644
index 000000000..bb5d664d0
--- /dev/null
+++ b/app/assets/javascripts/components/store/configureStore.jsx
@@ -0,0 +1,6 @@
+import { createStore } from 'redux';
+import appReducer from '../reducers';
+
+export default function configureStore(initialState) {
+  return createStore(appReducer, initialState);
+}