Information: NavEx is currently being tested. Please notify about any bugs that might be there in Issues. Contributions welcome. NavEx is the navigation history package for Elixir/Phoenix Framework. It uses adapter pattern and lets you choose between a few adapters to keep your users navigation history.

Adapters

Keeps user's navigation history in the ETS. It saves user's identity in his session.

Keeps user's navigation history in session. Might lead to session overflow error when navigation history config or links are too long.

Installation

NavEx can be installed by adding nav_ex as a dependency in mix.exs:

def deps do
  [
    {:nav_ex, "~> 0.1.0"}
  ]
end

It might be added to HexDependencies once I feel that it is ready enough for it :D

Configuration:

  config :nav_ex,
    tracked_methods: ["GET"], # what methods to track
    excluded_paths: ["/admin", "/dev], # paths you won't need to keep track on
    history_length: 10, # what is the history list length per user
    adapter: NavEx.Adapters.ETS # adapter used by NavEx to save data
    adapter_config: %{
      ...
    }

Adapters

NavEx.Adapters.ETS

  ....
  adapter_config: %{
    identity_key: "nav_ex_identity", # name of the key in session where the user's identity is saved
    table_name: :navigation_history # name of the ETS table
  }

This adapter supports LiveView sockets.

NavEx.Adapters.Session

  ....
  adapter_config: %{
    history_key: "nav_ex_history" # name of the key in session where navigation history is saved
  }

This adapter doesn't support LiveView sockets.

Usage

For normal routes.

defmodule MyApp.Router do
  ...
  pipeline :browser do
    ...
    plug NavEx.Plug
  end
  ...
end

For LiveView routes (live session routing included) (ETS adapter only)

# you can use LiveView's on_mount callback to set and DRY
def mount(_params, %{"nav_ex_identity" => identity} = session, socket) do
  socket = assign(socket, :nav_ex_identity, identity)
  ...
  {:ok, socket}
end

def handle_params(_params, uri, socket) do
  path = ... path from uri logic
  NavEx.insert(socket, uri)
  ...

  {:noreply, socket}
end

NavEx.last_path/1
It returns 2nd last path.

# for existing user
iex(1)> NavEx.last_path(conn)
{:ok, "/sample/path"}

# for existing user, but without 2 paths
iex(2)> NavEx.last_path(conn)
{:ok, nil}

# for not existing user
iex(3)> NavEx.last_path(conn)
{:error, :not_found}

NavEx.path_at/2
It returns Nth path counted from 0.

# for existing user
iex(1)> NavEx.path_at(conn, 5)
{:ok, "/sample/path"}

# for existing user but exceeding paths number
iex(2)> NavEx.path_at(conn, 5)
{:ok, nil}

# for not existing user
iex(3)> NavEx.path_at(conn, 5)
{:error, :not_found}

iex(4)> NavEx.path_at(conn, 999)
** (ArgumentError) Max history depth is 10 counted from 0 to 9. You asked for record number 999.

NavEx.list/1
Lists user's paths. Older paths have higher indexes.

# for existing user
iex(1)> NavEx.list(conn)
{:ok, ["/sample/path/2", "sample/path/1]}

# for not existing user
iex(2)> NavEx.list(conn)
{:error, :not_found}