Permalink
Browse files

Todo socket and channel for realtime TODO notifications

  • Loading branch information...
slashdotdash committed Nov 10, 2015
1 parent e01c593 commit 5c67bb9069c1770de0ec802ac0659fdfb6ac0631
@@ -1,7 +1,7 @@
defmodule PhoenixReactReduxExample.Endpoint do
use Phoenix.Endpoint, otp_app: :phoenix_react_redux_example
socket "/ws", PhoenixReactReduxExample.UserSocket
socket "/ws", PhoenixReactReduxExample.TodoSocket
# Serve at "/" the static files from "priv/static" directory.
#
@@ -0,0 +1,15 @@
defmodule PhoenixReactReduxExample.TodoChannel do
use PhoenixReactReduxExample.Web, :channel
def join("todos:" <> todo_id, _params, socket) do
{:ok, assign(socket, :todo_id, todo_id) }
end
def handle_in("new:todo", params, socket) do
broadcast! socket, "new:todo", %{
text: params["text"]
}
{:reply, :ok, socket}
end
end
@@ -1,8 +1,8 @@
defmodule PhoenixReactReduxExample.UserSocket do
defmodule PhoenixReactReduxExample.TodoSocket do
use Phoenix.Socket
## Channels
# channel "rooms:*", PhoenixReactReduxExample.RoomChannel
channel "todos:*", PhoenixReactReduxExample.TodoChannel
## Transports
transport :websocket, Phoenix.Transports.WebSocket
@@ -34,4 +34,4 @@ defmodule PhoenixReactReduxExample.UserSocket do
#
# Returning `nil` makes this socket anonymous.
def id(_socket), do: nil
end
end
@@ -1,3 +1,7 @@
import { configureChannel } from './channel';
let channel = configureChannel();
/*
* action types
*/
@@ -31,20 +35,41 @@ function addTodoSuccess(text) {
return { type: ADD_TODO_SUCCESS, text };
}
function addTodoFailure(text) {
return { type: ADD_TODO_FAILURE, text };
function addTodoFailure(text, error) {
return { type: ADD_TODO_FAILURE, text, error };
}
export function addTodo(text) {
return dispatch => {
dispatch(addTodoRequest(text));
let payload = {
text: text
};
console.log('adding todo');
// add todo, then dispatch success/failure
dispatch(addTodoSuccess(text));
dispatch(addTodoFailure(text));
channel.push('new:todo', payload)
.receive('ok', response => {
console.log('created TODO', response);
// dispatch(addTodoSuccess(text));
})
.receive('error', error => {
console.error(error);
dispatch(addTodoFailure(text, error));
});
};
}
export function subscribeTodos() {
return dispatch => {
channel.on('new:todo', msg => {
console.log('new:todo', msg);
dispatch(addTodoSuccess(msg.text));
});
};
}
export function completeTodo(index) {
return { type: COMPLETE_TODO, index };
@@ -1,15 +1,19 @@
import { Socket } from 'phoenix';
export function configureChannel() {
let socket = new Socket('/ws');
let socket = new Socket('/ws', {
logger: (kind, msg, data) => { console.log(`${kind}: ${msg}`, data); }
});
socket.connect();
let channel = socket.channel('todos');
let channel = socket.channel('todos:1');
channel.on('new:todo', msg => console.log('new:todo', msg));
channel.join()
.receive('ok', messages => console.log('catching up', messages))
.receive('error', reason => console.log('failed join', reason))
.after(10000, () => console.log('Networking issue. Still waiting...'));
return channel;
}
@@ -1,11 +1,17 @@
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { addTodo, completeTodo, setVisibilityFilter, VisibilityFilters } from '../actions';
import { subscribeTodos, addTodo, completeTodo, setVisibilityFilter, VisibilityFilters } from '../actions';
import AddTodo from '../components/AddTodo';
import TodoList from '../components/TodoList';
import Footer from '../components/Footer';
class App extends Component {
componentDidMount() {
let { dispatch } = this.props;
dispatch(subscribeTodos());
}
render() {
// Injected by connect() call:
const { dispatch, visibleTodos, visibilityFilter } = this.props;
@@ -6,7 +6,6 @@ import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import App from './containers/App';
import todoApp from './reducers';
import { configureChannel } from './channel';
const loggerMiddleware = createLogger();
@@ -17,8 +16,6 @@ const createStoreWithMiddleware = applyMiddleware(
const store = createStoreWithMiddleware(todoApp);
configureChannel(store);
render(
<Provider store={store}>
<App />
@@ -15,16 +15,18 @@ function visibilityFilter(state = SHOW_ALL, action) {
function todos(state = [], action) {
switch (action.type) {
case ADD_TODO_REQUEST:
return state;
case ADD_TODO_SUCCESS:
console.log('ADD_TODO_SUCCESS');
return [
...state,
{
text: action.text,
completed: false
}
];
case ADD_TODO_SUCCESS:
console.log('ADD_TODO_SUCCESS');
return state;
case ADD_TODO_FAILURE:
console.error('ADD_TODO_FAILURE');

0 comments on commit 5c67bb9

Please sign in to comment.