Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Todo socket and channel for realtime TODO notifications
  • Loading branch information
slashdotdash committed Nov 10, 2015
1 parent e01c593 commit 5c67bb9
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 18 deletions.
2 changes: 1 addition & 1 deletion lib/phoenix_react_redux_example/endpoint.ex
@@ -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.
#
Expand Down
15 changes: 15 additions & 0 deletions web/channels/todo_channel.ex
@@ -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
6 changes: 3 additions & 3 deletions web/channels/user_socket.ex → web/channels/todo_socket.ex
@@ -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
Expand Down Expand Up @@ -34,4 +34,4 @@ defmodule PhoenixReactReduxExample.UserSocket do
#
# Returning `nil` makes this socket anonymous.
def id(_socket), do: nil
end
end
33 changes: 29 additions & 4 deletions web/static/js/actions.js
@@ -1,3 +1,7 @@
import { configureChannel } from './channel';

let channel = configureChannel();

/*
* action types
*/
Expand Down Expand Up @@ -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 };
Expand Down
10 changes: 7 additions & 3 deletions web/static/js/channel.js
@@ -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;
}
8 changes: 7 additions & 1 deletion web/static/js/containers/App.js
@@ -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;
Expand Down
3 changes: 0 additions & 3 deletions web/static/js/index.js
Expand Up @@ -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();

Expand All @@ -17,8 +16,6 @@ const createStoreWithMiddleware = applyMiddleware(

const store = createStoreWithMiddleware(todoApp);

configureChannel(store);

render(
<Provider store={store}>
<App />
Expand Down
8 changes: 5 additions & 3 deletions web/static/js/reducers.js
Expand Up @@ -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');
Expand Down

0 comments on commit 5c67bb9

Please sign in to comment.