From 43a13160afcaebc0e6fe1cb09da5a1c7a3887eed Mon Sep 17 00:00:00 2001 From: Troy Martin Date: Mon, 17 Feb 2020 14:21:48 -0500 Subject: [PATCH] Add partial reloads --- .github/workflows/ci.yml | 51 ++++++++++-------------- CHANGELOG.md | 12 ++++++ README.md | 3 +- lib/inertia_phoenix/controller.ex | 37 +++++++++++++++++ mix.exs | 7 +++- mix.lock | 9 +++++ test/inertia_phoenix/controller_test.exs | 47 ++++++++++++++++++++++ 7 files changed, 134 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c885c58..2e438be 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,34 +3,27 @@ name: CI on: push jobs: - build: - + test: runs-on: ubuntu-latest - - container: - image: elixir:1.10.1 - env: - MIX_ENV: test - SECRET_KEY_BASE: test - + name: OTP ${{matrix.otp}} / Elixir ${{matrix.elixir}} + strategy: + matrix: + otp: [21.3.8.13, 22.2.6] + elixir: [1.9.4, 1.10.1] + env: + MIX_ENV: test + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - - - uses: actions/checkout@v2 - - - uses: actions/cache@v1 - with: - path: deps - key: ${{ runner.os }}-mix-${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }} - restore-keys: | - ${{ runner.os }}-mix- - - - name: Install Dependencies - run: | - mix local.rebar --force - mix local.hex --force - mix deps.get - - name: Run Tests - run: mix test - - - name: Run Credo - run: mix credo + - uses: actions/checkout@v2 + - uses: actions/cache@v1 + with: + path: deps + key: ${{ runner.os }}-mix-${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }} + restore-keys: | + ${{ runner.os }}-mix- + - uses: actions/setup-elixir@v1.0.0 + with: + otp-version: ${{matrix.otp}} + elixir-version: ${{matrix.elixir}} + - run: mix deps.get + - run: mix coveralls.github diff --git a/CHANGELOG.md b/CHANGELOG.md index b3649f0..76669a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [Unreleased](https://github.com/devato/inertia_phoenix/tree/HEAD) + +[Full Changelog](https://github.com/devato/inertia_phoenix/compare/0.1.7...HEAD) + +**Implemented enhancements:** + +- Add config for layout [\#10](https://github.com/devato/inertia_phoenix/issues/10) + +## [0.1.7](https://github.com/devato/inertia_phoenix/tree/0.1.7) (2020-02-17) + +[Full Changelog](https://github.com/devato/inertia_phoenix/compare/0.1.6...0.1.7) + ## [0.1.6](https://github.com/devato/inertia_phoenix/tree/0.1.6) (2020-02-17) [Full Changelog](https://github.com/devato/inertia_phoenix/compare/0.1.5...0.1.6) diff --git a/README.md b/README.md index 818bfb4..0cda710 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Inertia Phoenix ![CI](https://github.com/devato/inertia_phoenix/workflows/CI/badge.svg) +![Coveralls](https://img.shields.io/coveralls/github/devato/inertia_phoenix) Inertiajs Adapter for Elixir Phoenix @@ -21,7 +22,7 @@ Inertiajs Adapter for Elixir Phoenix Add to mix.exs: ``` -{:inertia_phoenix, "~> 0.1.6"} +{:inertia_phoenix, "~> 0.1.7"} ``` Add Plug to `WEB_PATH/router.ex` diff --git a/lib/inertia_phoenix/controller.ex b/lib/inertia_phoenix/controller.ex index 883f01c..3d0c03d 100644 --- a/lib/inertia_phoenix/controller.ex +++ b/lib/inertia_phoenix/controller.ex @@ -1,6 +1,7 @@ defmodule InertiaPhoenix.Controller do @moduledoc false import InertiaPhoenix + import Plug.Conn, only: [get_req_header: 2] alias Phoenix.Controller def render_inertia(conn, component, assigns \\ [props: %{}]) @@ -8,6 +9,8 @@ defmodule InertiaPhoenix.Controller do def render_inertia(%{assigns: %{inertia_request: true}} = conn, component, assigns) do assigns = assigns + |> filter_partial_data(conn) + |> lazy_load() |> assign_component(component) |> assign_flash(Controller.get_flash(conn)) @@ -17,6 +20,8 @@ defmodule InertiaPhoenix.Controller do def render_inertia(conn, component, assigns) do assigns = assigns + |> filter_partial_data(conn) + |> lazy_load() |> assign_component(component) |> assign_flash(Controller.get_flash(conn)) @@ -46,4 +51,36 @@ defmodule InertiaPhoenix.Controller do defp assign_flash(assigns, flash) do put_in(assigns, [:props, :flash], flash) end + + defp filter_partial_data(assigns, conn) do + case get_req_header(conn, "x-inertia-partial-data") do + [] -> + assigns + + [partial_data] -> + requested_props = String.split(partial_data, ",") + + Keyword.put( + assigns, + :props, + assigns[:props] + |> Enum.filter(fn {k, _} -> Atom.to_string(k) in requested_props end) + ) + end + end + + defp lazy_load(assigns) do + Keyword.put( + assigns, + :props, + Enum.map(assigns[:props], fn {k, v} -> + if is_function(v) do + {k, v.()} + else + {k, v} + end + end) + |> Enum.into(%{}) + ) + end end diff --git a/mix.exs b/mix.exs index 61c5718..a799967 100644 --- a/mix.exs +++ b/mix.exs @@ -4,12 +4,14 @@ defmodule InertiaPhoenix.MixProject do def project do [ app: :inertia_phoenix, - version: "0.1.7", + version: "0.1.8", elixir: "~> 1.6", elixirc_paths: elixirc_paths(Mix.env()), start_permanent: Mix.env() == :prod, compilers: [:phoenix] ++ Mix.compilers(), deps: deps(), + test_coverage: [tool: ExCoveralls], + preferred_cli_env: [coveralls: :test, "coveralls.detail": :test, "coveralls.post": :test, "coveralls.html": :test], description: "Inertiajs adapter for Elixir Phoenix", package: package() ] @@ -32,7 +34,8 @@ defmodule InertiaPhoenix.MixProject do # Credo requires jason to exist also in :dev {:jason, "~> 1.0", only: [:dev, :test]}, {:ex_doc, "~> 0.21.0", only: :dev}, - {:plug_cowboy, "~> 2.1", only: [:test]} + {:plug_cowboy, "~> 2.1", only: [:test]}, + {:excoveralls, "~> 0.10", only: :test} ] end diff --git a/mix.lock b/mix.lock index 3fd0d4b..8ac1696 100644 --- a/mix.lock +++ b/mix.lock @@ -1,15 +1,22 @@ %{ "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, + "certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"}, "cowboy": {:hex, :cowboy, "2.7.0", "91ed100138a764355f43316b1d23d7ff6bdb0de4ea618cb5d8677c93a7a2f115", [:rebar3], [{:cowlib, "~> 2.8.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"}, "cowlib": {:hex, :cowlib, "2.8.0", "fd0ff1787db84ac415b8211573e9a30a3ebe71b5cbff7f720089972b2319c8a4", [:rebar3], [], "hexpm"}, "credo": {:hex, :credo, "1.2.2", "f57faf60e0a12b0ba9fd4bad07966057fde162b33496c509b95b027993494aab", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, "earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm"}, "ex_doc": {:hex, :ex_doc, "0.21.3", "857ec876b35a587c5d9148a2512e952e24c24345552259464b98bfbb883c7b42", [:mix], [{:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, + "excoveralls": {:hex, :excoveralls, "0.12.2", "a513defac45c59e310ac42fcf2b8ae96f1f85746410f30b1ff2b710a4b6cd44b", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, + "hackney": {:hex, :hackney, "1.15.2", "07e33c794f8f8964ee86cebec1a8ed88db5070e52e904b8f12209773c1036085", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.5", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, + "idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"}, "makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, "makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, + "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, "mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"}, + "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"}, "nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm"}, + "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"}, "phoenix": {:hex, :phoenix, "1.4.13", "67271ad69b51f3719354604f4a3f968f83aa61c19199343656c9caee057ff3b8", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"}, "phoenix_html": {:hex, :phoenix_html, "2.14.0", "d8c6bc28acc8e65f8ea0080ee05aa13d912c8758699283b8d3427b655aabe284", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.2", "496c303bdf1b2e98a9d26e89af5bba3ab487ba3a3735f74bf1f4064d2a845a3e", [:mix], [], "hexpm"}, @@ -17,5 +24,7 @@ "plug_cowboy": {:hex, :plug_cowboy, "2.1.2", "8b0addb5908c5238fac38e442e81b6fcd32788eaa03246b4d55d147c47c5805e", [:mix], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"}, "plug_crypto": {:hex, :plug_crypto, "1.1.1", "c6d605a0110f164b60d3e082fc862a42acd08483827f71278b4935980b1146b0", [:mix], [], "hexpm"}, "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm"}, "telemetry": {:hex, :telemetry, "0.4.1", "ae2718484892448a24470e6aa341bc847c3277bfb8d4e9289f7474d752c09c7f", [:rebar3], [], "hexpm"}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"}, } diff --git a/test/inertia_phoenix/controller_test.exs b/test/inertia_phoenix/controller_test.exs index ff627ba..93c4fc1 100644 --- a/test/inertia_phoenix/controller_test.exs +++ b/test/inertia_phoenix/controller_test.exs @@ -105,4 +105,51 @@ defmodule InertiaPhoenix.ControllerTest do assert html = html_response(conn, 303) end + + test "render_inertia/3 with x-inertia-partial-data", %{conn: conn} do + conn = + conn + |> Conn.put_req_header("x-inertia", "true") + |> Conn.put_req_header("x-inertia-version", "1") + |> Conn.put_req_header("x-inertia-partial-data", "hello,foo") + |> fetch_session + |> fetch_flash + |> InertiaPhoenix.Plug.call([]) + |> InertiaPhoenix.Controller.render_inertia("Home", + props: %{hello: "world", world: "hello", foo: "bar"} + ) + + page_map = %{ + "component" => "Home", + "props" => %{"hello" => "world", "foo" => "bar"}, + "url" => "/", + "version" => "1" + } + + assert json = json_response(conn, 200) + assert json == page_map + end + + test "render_inertia/3 with lazy loaded prop", %{conn: conn} do + conn = + conn + |> Conn.put_req_header("x-inertia", "true") + |> Conn.put_req_header("x-inertia-version", "1") + |> fetch_session + |> fetch_flash + |> InertiaPhoenix.Plug.call([]) + |> InertiaPhoenix.Controller.render_inertia("Home", + props: %{hello: fn -> "world" end, foo: "bar"} + ) + + page_map = %{ + "component" => "Home", + "props" => %{"hello" => "world", "foo" => "bar"}, + "url" => "/", + "version" => "1" + } + + assert json = json_response(conn, 200) + assert json == page_map + end end