lib/ex_teal/dashboard.ex

defmodule ExTeal.Dashboard do
  @moduledoc """
  Module used to represent a dashboard which contains a grid of metrics, this will one day be extendable to include
  plugin or custom cards in the future.
  """

  alias ExTeal.Card

  @type range :: %{
          label: String.t(),
          unit: String.t(),
          value: integer()
        }

  @callback title() :: String.t()

  @doc """
  Unique URI that allows the dashboard to look up cards.  Should be url safe.
  """
  @callback uri() :: String.t()

  @doc """
  Return the modules that represent cards on the
  dashboard.
  """
  @callback cards(Plug.Conn.t()) :: [module()]

  @doc """
  Show or Hide a dashboard based on the current connection. Defaults to true
  """
  @callback display?(Plug.Conn.t()) :: boolean()

  defmacro __using__(_) do
    quote do
      @behaviour ExTeal.Dashboard
      alias ExTeal.Dashboard
      alias ExTeal.Resource.Model

      @implied_title Model.title_from_resource(__MODULE__)
      @implied_uri Phoenix.Naming.underscore(@implied_title)

      def title do
        @implied_title
        |> Inflex.singularize()
      end

      def uri do
        @implied_uri
        |> Inflex.underscore()
        |> String.replace(" ", "_")
      end

      def cards(_conn), do: []

      def display?(_conn), do: true

      defoverridable title: 0, cards: 1, uri: 0, display?: 1
    end
  end

  def map_to_json(modules) do
    modules
    |> Enum.map(fn module ->
      %{
        title: module.title(),
        uri: module.uri()
      }
    end)
  end

  def cards_to_json(dashboard_module, conn) do
    cards =
      conn
      |> dashboard_module.cards()
      |> Enum.map(&Card.to_struct(&1, conn))

    %{cards: cards}
  end
end