From 5041f8fa2cf7c51d8d9837ea7cfd0095e57027a1 Mon Sep 17 00:00:00 2001 From: Tim Mecklem Date: Thu, 14 Jun 2018 14:21:37 -0400 Subject: [PATCH] Prepend broadcasted transaction to address transactions list Co-authored-by: Stamates Co-authored-by: Tim Mecklem --- apps/explorer_web/assets/js/app.js | 6 ++ apps/explorer_web/assets/js/socket.js | 65 ++++--------------- .../explorer_web/channels/address_channel.ex | 15 +++++ .../lib/explorer_web/channels/user_socket.ex | 27 +------- apps/explorer_web/lib/explorer_web/router.ex | 1 + .../templates/address/_link.html.eex | 2 +- .../templates/address/overview.html.eex | 4 ++ .../index.html.eex | 6 +- .../address_transaction/_transaction.html.eex | 35 ++++++++++ .../address_transaction/index.html.eex | 12 ++-- .../block_transaction/index.html.eex | 6 +- .../templates/chain/_blocks.html.eex | 2 +- .../templates/chain/_transactions.html.eex | 6 +- .../pending_transaction/index.html.eex | 6 +- .../templates/transaction/_link.html.eex | 2 +- .../templates/transaction/index.html.eex | 6 +- .../index.html.eex | 4 +- .../features/viewing_addresses_test.exs | 17 +++++ 18 files changed, 119 insertions(+), 103 deletions(-) create mode 100644 apps/explorer_web/lib/explorer_web/channels/address_channel.ex create mode 100644 apps/explorer_web/lib/explorer_web/templates/address_transaction/_transaction.html.eex diff --git a/apps/explorer_web/assets/js/app.js b/apps/explorer_web/assets/js/app.js index ffdc9e43bd..d916951d56 100644 --- a/apps/explorer_web/assets/js/app.js +++ b/apps/explorer_web/assets/js/app.js @@ -18,7 +18,13 @@ import 'bootstrap' // Local files can be imported directly using relative // paths "./socket" or full ones "web/static/js/socket". +<<<<<<< HEAD // import socket from "./socket" +======= +import './socket' +import './lib/sidebar' +import './lib/market_history_chart' +>>>>>>> Prepend broadcasted transaction to address transactions list import './lib/card_flip' import './lib/clipboard_buttons' import './lib/from_now' diff --git a/apps/explorer_web/assets/js/socket.js b/apps/explorer_web/assets/js/socket.js index 274e526e63..cc814e27db 100644 --- a/apps/explorer_web/assets/js/socket.js +++ b/apps/explorer_web/assets/js/socket.js @@ -1,62 +1,21 @@ -// NOTE: The contents of this file will only be executed if -// you uncomment its entry in "assets/js/app.js". - -// To use Phoenix channels, the first step is to import Socket -// and connect at the socket path in "lib/web/endpoint.ex": import {Socket} from 'phoenix' +import $ from 'jquery' -let socket = new Socket('/socket', {params: {token: window.userToken}}) - -// When you connect, you'll often need to authenticate the client. -// For example, imagine you have an authentication plug, `MyAuth`, -// which authenticates the session and assigns a `:current_user`. -// If the current user exists you can assign the user's token in -// the connection for use in the layout. -// -// In your "lib/web/router.ex": -// -// pipeline :browser do -// ... -// plug MyAuth -// plug :put_user_token -// end -// -// defp put_user_token(conn, _) do -// if current_user = conn.assigns[:current_user] do -// token = Phoenix.Token.sign(conn, "user socket", current_user.id) -// assign(conn, :user_token, token) -// else -// conn -// end -// end -// -// Now you need to pass this token to JavaScript. You can do so -// inside a script tag in "lib/web/templates/layout/app.html.eex": -// -// -// -// You will need to verify the user token in the "connect/2" function -// in "lib/web/channels/user_socket.ex": -// -// def connect(%{"token" => token}, socket) do -// # max_age: 1209600 is equivalent to two weeks in seconds -// case Phoenix.Token.verify(socket, "user socket", token, max_age: 1209600) do -// {:ok, user_id} -> -// {:ok, assign(socket, :user, user_id)} -// {:error, reason} -> -// :error -// end -// end -// -// Finally, pass the token on connect as below. Or remove it -// from connect if you don't care about authentication. - +let socket = new Socket('/socket', {params: {locale: window.locale}}) socket.connect() -// Now that you are connected, you can join channels with a topic: -let channel = socket.channel('topic:subtopic', {}) + + + + +// addresses channel +let channel = socket.channel(`addresses:${window.addressHash}`, {}) channel.join() .receive('ok', resp => { console.log('Joined successfully', resp) }) .receive('error', resp => { console.log('Unable to join', resp) }) +channel.on('transaction', (msg) => { + $('[data-selector="transactions-list"]').prepend(msg.transaction) +}) + export default socket diff --git a/apps/explorer_web/lib/explorer_web/channels/address_channel.ex b/apps/explorer_web/lib/explorer_web/channels/address_channel.ex new file mode 100644 index 0000000000..a493b47868 --- /dev/null +++ b/apps/explorer_web/lib/explorer_web/channels/address_channel.ex @@ -0,0 +1,15 @@ +defmodule ExplorerWeb.AddressChannel do + use ExplorerWeb, :channel + + intercept ["transaction"] + + def join("addresses:" <> _address_hash, _params, socket) do + {:ok, %{}, socket} + end + + def handle_out("transaction", %{transaction: transaction}, socket) do + rendered = Phoenix.View.render_to_string(ExplorerWeb.AddressTransactionView, "_transaction.html", locale: socket.assigns.locale, transaction: transaction) + push socket, "transaction", %{transaction: rendered} + {:noreply, socket} + end +end diff --git a/apps/explorer_web/lib/explorer_web/channels/user_socket.ex b/apps/explorer_web/lib/explorer_web/channels/user_socket.ex index 8db7d44814..caf021bc24 100644 --- a/apps/explorer_web/lib/explorer_web/channels/user_socket.ex +++ b/apps/explorer_web/lib/explorer_web/channels/user_socket.ex @@ -1,35 +1,14 @@ defmodule ExplorerWeb.UserSocket do use Phoenix.Socket - # channel "room:*", ExplorerWeb.RoomChannel + channel "addresses:*", ExplorerWeb.AddressChannel transport(:websocket, Phoenix.Transports.WebSocket, timeout: 45_000) # transport :longpoll, Phoenix.Transports.LongPoll - # Socket params are passed from the client and can - # be used to verify and authenticate a user. After - # verification, you can put default assigns into - # the socket that will be set for all channels, ie - # - # {:ok, assign(socket, :user_id, verified_user_id)} - # - # To deny connection, return `:error`. - # - # See `Phoenix.Token` documentation for examples in - # performing token verification on connect. - def connect(_params, socket) do - {:ok, socket} + def connect(%{"locale" => locale}, socket) do + {:ok, assign(socket, :locale, locale)} end - # Socket ids are topics that allow you to identify all sockets for a user: - # - # def id(socket), do: "user_socket:#{socket.assigns.user_id}" - # - # Would allow you to broadcast a "disconnect" event and terminate - # all active sockets and channels for a given user: - # - # ExplorerWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{}) - # - # Returning `nil` makes this socket anonymous. def id(_socket), do: nil end diff --git a/apps/explorer_web/lib/explorer_web/router.ex b/apps/explorer_web/lib/explorer_web/router.ex index 7bcabd3caa..a1bf5713ff 100644 --- a/apps/explorer_web/lib/explorer_web/router.ex +++ b/apps/explorer_web/lib/explorer_web/router.ex @@ -9,6 +9,7 @@ defmodule ExplorerWeb.Router do plug(:put_secure_browser_headers, %{ "content-security-policy" => "\ + connect-src 'self' ws://localhost:*;\ default-src 'self';\ script-src 'self' 'unsafe-inline' 'unsafe-eval';\ style-src 'self' 'unsafe-inline' 'unsafe-eval' https://fonts.googleapis.com;\ diff --git a/apps/explorer_web/lib/explorer_web/templates/address/_link.html.eex b/apps/explorer_web/lib/explorer_web/templates/address/_link.html.eex index b0663d7310..22272f40b8 100644 --- a/apps/explorer_web/lib/explorer_web/templates/address/_link.html.eex +++ b/apps/explorer_web/lib/explorer_web/templates/address/_link.html.eex @@ -1,6 +1,6 @@