feat: Setup LiveView
This commit is contained in:
parent
736b0d8296
commit
8929fd8204
24 changed files with 16075 additions and 68 deletions
|
@ -50,7 +50,7 @@ defmodule Legendary.Admin.MixProject do
|
|||
{:phoenix_ecto, "~> 4.0"},
|
||||
{:phoenix_html, "~> 2.11"},
|
||||
{:phoenix_live_reload, "~> 1.2", only: :dev},
|
||||
{:phoenix_live_dashboard, "~> 0.2.0"},
|
||||
{:phoenix_live_dashboard, "~> 0.4.0"},
|
||||
{:postgrex, ">= 0.0.0"},
|
||||
{:telemetry_metrics, "~> 0.4"},
|
||||
{:telemetry_poller, "~> 0.4"},
|
||||
|
|
|
@ -14,6 +14,7 @@ import "../css/app.css"
|
|||
//
|
||||
import "phoenix_html"
|
||||
import "alpinejs"
|
||||
import "./live"
|
||||
import { ready } from "./utils"
|
||||
|
||||
function togglePasswordFieldVisibility()
|
||||
|
@ -38,7 +39,7 @@ const toggleSidebar = (event) => {
|
|||
}
|
||||
|
||||
ready(() => {
|
||||
document.getElementById('nav-toggle').onclick = function(){
|
||||
(document.getElementById('nav-toggle') ||{}).onclick = function(){
|
||||
document.getElementById("nav-content").classList.toggle("hidden");
|
||||
}
|
||||
|
||||
|
|
23
apps/app/assets/js/live.js
Normal file
23
apps/app/assets/js/live.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
import {Socket} from "phoenix"
|
||||
import LiveSocket from "phoenix_live_view"
|
||||
import topbar from "topbar"
|
||||
|
||||
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
|
||||
|
||||
let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}})
|
||||
|
||||
// Show progress bar on live navigation and form submits
|
||||
topbar.config({barColors: {0: "#3B82F6"}, shadowColor: "rgba(0, 0, 0, .3)"})
|
||||
window.addEventListener("phx:page-loading-start", info => topbar.show())
|
||||
window.addEventListener("phx:page-loading-stop", info => topbar.hide())
|
||||
|
||||
// Connect if there are any LiveViews on the page
|
||||
liveSocket.connect()
|
||||
|
||||
// Expose liveSocket on window for web console debug logs and latency simulation:
|
||||
// >> liveSocket.enableDebug()
|
||||
// >> liveSocket.enableLatencySim(1000)
|
||||
// The latency simulator is enabled for the duration of the browser session.
|
||||
// Call disableLatencySim() to disable:
|
||||
// >> liveSocket.disableLatencySim()
|
||||
window.liveSocket = liveSocket
|
15866
apps/app/assets/package-lock.json
generated
15866
apps/app/assets/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -16,10 +16,12 @@
|
|||
"gulp": "^4.0.2",
|
||||
"phoenix": "file:/../../../deps/phoenix",
|
||||
"phoenix_html": "file:/../../../deps/phoenix_html",
|
||||
"phoenix_live_view": "file:../../../deps/phoenix_live_view",
|
||||
"postcss-color-function": "^4.1.0",
|
||||
"simplemde": "^1.11.2",
|
||||
"stylelint": "^13.6.1",
|
||||
"tailwindcss": "^1.7.3"
|
||||
"tailwindcss": "^1.7.3",
|
||||
"topbar": "^1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.0.0",
|
||||
|
|
|
@ -27,6 +27,27 @@ defmodule AppWeb do
|
|||
end
|
||||
end
|
||||
|
||||
def live_view do
|
||||
quote do
|
||||
use Phoenix.LiveView,
|
||||
layout: {AppWeb.LayoutView, "live.html"}
|
||||
|
||||
import AppWeb.LiveHelpers
|
||||
|
||||
unquote(view_helpers())
|
||||
end
|
||||
end
|
||||
|
||||
def live_component do
|
||||
quote do
|
||||
use Phoenix.LiveComponent
|
||||
|
||||
import AppWeb.LiveHelpers
|
||||
|
||||
unquote(view_helpers())
|
||||
end
|
||||
end
|
||||
|
||||
def view do
|
||||
quote do
|
||||
use Phoenix.View,
|
||||
|
@ -48,6 +69,7 @@ defmodule AppWeb do
|
|||
|
||||
import Plug.Conn
|
||||
import Phoenix.Controller
|
||||
import Phoenix.LiveView.Router
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -66,9 +88,10 @@ defmodule AppWeb do
|
|||
# Import basic rendering functionality (render, render_layout, etc)
|
||||
import Phoenix.View
|
||||
|
||||
import Legendary.CoreWeb.Helpers
|
||||
import AppWeb.ErrorHelpers
|
||||
import AppWeb.Gettext
|
||||
import Legendary.CoreWeb.Helpers
|
||||
import Phoenix.LiveView.Helpers
|
||||
alias AppWeb.Router.Helpers, as: Routes
|
||||
end
|
||||
end
|
||||
|
|
0
apps/app/lib/app_web/live/.keep
Normal file
0
apps/app/lib/app_web/live/.keep
Normal file
41
apps/app/lib/app_web/live_helpers.ex
Normal file
41
apps/app/lib/app_web/live_helpers.ex
Normal file
|
@ -0,0 +1,41 @@
|
|||
defmodule AppWeb.LiveHelpers do
|
||||
@moduledoc """
|
||||
Commonly functions for LiveViews.
|
||||
"""
|
||||
import Phoenix.LiveView
|
||||
|
||||
alias Legendary.Auth.User
|
||||
alias Pow.Store.CredentialsCache
|
||||
alias AppWeb.Pow.Routes
|
||||
|
||||
def assign_defaults(socket, session) do
|
||||
assign_new(socket, :current_user, fn -> get_user(socket, session) end)
|
||||
end
|
||||
|
||||
def require_auth(socket) do
|
||||
if socket.assigns.current_user do
|
||||
socket
|
||||
else
|
||||
redirect(socket, to: Routes.after_sign_out_path(%Plug.Conn{}))
|
||||
end
|
||||
end
|
||||
|
||||
defp get_user(socket, session, config \\ [otp_app: :core])
|
||||
|
||||
defp get_user(socket, %{"core_auth" => signed_token}, config) do
|
||||
{otp_app, _config} = Keyword.pop(config, :otp_app, :core)
|
||||
{store, store_config} = Pow.Plug.Base.store(Application.get_env(otp_app, :pow))
|
||||
|
||||
conn = struct!(Plug.Conn, secret_key_base: socket.endpoint.config(:secret_key_base))
|
||||
salt = Atom.to_string(Pow.Plug.Session)
|
||||
|
||||
with {:ok, token} <- Pow.Plug.verify_token(conn, salt, signed_token, config),
|
||||
{user, _metadata} <- store.get(store_config, token) do
|
||||
user
|
||||
else
|
||||
_any -> nil
|
||||
end
|
||||
end
|
||||
|
||||
defp get_user(_, _, _), do: nil
|
||||
end
|
|
@ -9,10 +9,11 @@ defmodule AppWeb.Router do
|
|||
pipeline :browser do
|
||||
plug :accepts, ["html"]
|
||||
plug :fetch_session
|
||||
plug :fetch_flash
|
||||
plug :fetch_live_flash
|
||||
plug :protect_from_forgery
|
||||
plug :put_secure_browser_headers
|
||||
plug :put_layout, {AppWeb.LayoutView, :app}
|
||||
plug :put_root_layout, {AppWeb.LayoutView, :root}
|
||||
end
|
||||
|
||||
pipeline :api do
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<div class="fixed w-full px-4 z-50 mt-20">
|
||||
<%= [info: "green", error: "red"] |> Enum.map(fn {level, color} -> %>
|
||||
<%= if live_flash(@flash, level) do %>
|
||||
<div
|
||||
class="relative bg-<%= color %>-100 lg:w-1/2 w-full p-5 object-right rounded shadow-xl m-auto mb-5 js-flash"
|
||||
phx-click="lv:clear-flash"
|
||||
phx-value-key="<%= level %>"
|
||||
>
|
||||
<div class="flex justify-between text-<%= color %>-700">
|
||||
<div class="flex space-x-3">
|
||||
<div class="flex-1 leading-tight text-sm font-medium">
|
||||
<%= live_flash(@flash, level) %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-none">
|
||||
×
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end) %>
|
||||
</div>
|
|
@ -1,3 +1,5 @@
|
|||
<% conn_or_socket = if assigns[:conn], do: assigns[:conn], else: @socket %>
|
||||
|
||||
<nav class="flex items-center justify-between flex-wrap bg-grey-dark p-6 w-full z-10 bg-gray-800">
|
||||
<div class="flex items-center flex-no-shrink text-white mr-6">
|
||||
<a class="text-white no-underline hover:text-white hover:no-underline" href="/">
|
||||
|
@ -13,23 +15,23 @@
|
|||
|
||||
<div class="w-full flex-grow lg:flex lg:items-center lg:w-auto hidden lg:block pt-6 lg:pt-0" id="nav-content">
|
||||
<ul class="list-reset lg:flex justify-end flex-1 items-center">
|
||||
<%= if has_role?(@conn, :admin) do %>
|
||||
<%= if has_role?(conn_or_socket, :admin) do %>
|
||||
<li class="mr-3">
|
||||
<a class="inline-block py-2 px-4 text-white no-underline" href="/admin">Admin</a>
|
||||
</li>
|
||||
<% end %>
|
||||
<%= if Pow.Plug.current_user(@conn) do %>
|
||||
<%= if current_user(conn_or_socket) do %>
|
||||
<li class="mr-3">
|
||||
<%= link "Sign Out", to: Routes.pow_session_path(@conn, :delete), method: :delete, class: "inline-block text-white no-underline hover:text-white hover:text-underline py-2 px-4" %>
|
||||
<%= link "Sign Out", to: Routes.pow_session_path(conn_or_socket, :delete), method: :delete, class: "inline-block text-white no-underline hover:text-white hover:text-underline py-2 px-4" %>
|
||||
</li>
|
||||
<% else %>
|
||||
<li class="mr-3">
|
||||
<%= link to: Routes.pow_session_path(@conn, :new), class: "inline-block text-white no-underline hover:text-white hover:text-underline py-2 px-4" do %>
|
||||
<%= link to: Routes.pow_session_path(conn_or_socket, :new), class: "inline-block text-white no-underline hover:text-white hover:text-underline py-2 px-4" do %>
|
||||
Log In
|
||||
<% end %>
|
||||
</li>
|
||||
<li class="mr-3">
|
||||
<%= link to: Routes.pow_registration_path(@conn, :new), class: "inline-block text-white no-underline hover:text-white hover:text-underline py-2 px-4" do %>
|
||||
<%= link to: Routes.pow_registration_path(conn_or_socket, :new), class: "inline-block text-white no-underline hover:text-white hover:text-underline py-2 px-4" do %>
|
||||
Sign Up
|
||||
<% end %>
|
||||
</li>
|
||||
|
|
|
@ -1,24 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title><%= title(@view_module, @view_template, assigns) %></title>
|
||||
<link rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
|
||||
<%= feed_tag(@conn, @view_module, @view_template, assigns) %>
|
||||
<script defer type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
|
||||
</head>
|
||||
<body class="text-gray-800 antialiased">
|
||||
<main role="main">
|
||||
<!-- Page Contents -->
|
||||
<div class="bg-gray-100 min-h-screen">
|
||||
<%= render "_menu.html", assigns %>
|
||||
<%= render "_menu.html", assigns %>
|
||||
|
||||
<%= flash_block(@conn) %>
|
||||
<%= flash_block(@conn) %>
|
||||
|
||||
<%= @inner_content %>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
<%= @inner_content %>
|
||||
|
|
6
apps/app/lib/app_web/templates/layout/live.html.leex
Normal file
6
apps/app/lib/app_web/templates/layout/live.html.leex
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
<%= render "_menu.html", assigns %>
|
||||
|
||||
<%= render "_live_flash_block.html", flash: @flash %>
|
||||
|
||||
<%= @inner_content %>
|
20
apps/app/lib/app_web/templates/layout/root.html.leex
Normal file
20
apps/app/lib/app_web/templates/layout/root.html.leex
Normal file
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<%= csrf_meta_tag() %>
|
||||
<%= live_title_tag title(@view_module, @view_template, assigns) %>
|
||||
<link phx-track-static rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
|
||||
<script defer phx-track-static type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
|
||||
</head>
|
||||
<body class="text-gray-800 antialiased">
|
||||
<main role="main">
|
||||
<!-- Page Contents -->
|
||||
<div class="bg-gray-100 min-h-screen">
|
||||
<%= @inner_content %>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
|
@ -44,12 +44,14 @@ defmodule App.MixProject do
|
|||
{:core, in_umbrella: true},
|
||||
{:ecto_sql, "~> 3.4"},
|
||||
{:excoveralls, "~> 0.10", only: [:dev, :test]},
|
||||
{:floki, ">= 0.30.0"},
|
||||
{:oban, "~> 2.1"},
|
||||
{:phoenix, "~> 1.5.8"},
|
||||
{:phoenix_ecto, "~> 4.0"},
|
||||
{:phoenix_html, "~> 2.11"},
|
||||
{:phoenix_live_reload, "~> 1.2", only: :dev},
|
||||
{:phoenix_live_dashboard, "~> 0.2.0"},
|
||||
{:phoenix_live_dashboard, "~> 0.4.0"},
|
||||
{:phoenix_live_view, "~> 0.15.7", override: true},
|
||||
{:postgrex, ">= 0.0.0"},
|
||||
{:telemetry_metrics, "~> 0.4"},
|
||||
{:telemetry_poller, "~> 0.4"},
|
||||
|
|
|
@ -3,8 +3,6 @@ defmodule Legendary.Content.FeedsController do
|
|||
|
||||
alias Legendary.Content.{Posts}
|
||||
|
||||
plug :put_layout, false when action in [:preview]
|
||||
|
||||
def index(conn, params) do
|
||||
category = params |> Map.get("category")
|
||||
posts = Posts.list_posts(params)
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title><%= title(@view_module, @view_template, assigns) %></title>
|
||||
<link rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
|
||||
<link phx-track-static rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
|
||||
<%= feed_tag(@conn, @view_module, @view_template, assigns) %>
|
||||
<script defer type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
|
||||
<script phx-track-static defer type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
|
||||
</head>
|
||||
<body class="text-gray-800 antialiased">
|
||||
<main role="main">
|
||||
|
|
|
@ -44,7 +44,7 @@ defmodule Legendary.Content.MixProject do
|
|||
{:core, in_umbrella: true},
|
||||
{:earmark, "1.4.3"},
|
||||
{:excoveralls, "~> 0.10", only: [:dev, :test]},
|
||||
{:floki, "~> 0.25.0"},
|
||||
{:floki, ">= 0.30.0"},
|
||||
{:gettext, "~> 0.11"},
|
||||
{:jason, "~> 1.0"},
|
||||
{:mock, "~> 0.3.0", only: :test},
|
||||
|
@ -56,7 +56,7 @@ defmodule Legendary.Content.MixProject do
|
|||
{:phoenix_html, "~> 2.11"},
|
||||
{:phoenix_html_sanitizer, "~> 1.0.0"},
|
||||
{:phoenix_live_reload, "~> 1.2", only: :dev},
|
||||
{:phoenix_live_dashboard, "~> 0.2.0"},
|
||||
{:phoenix_live_dashboard, "~> 0.4.0"},
|
||||
{:php_serializer, "~> 0.9.0"},
|
||||
{:plug_cowboy, "~> 2.0"},
|
||||
{:sitemap, "~> 1.1"},
|
||||
|
|
45
apps/core/lib/auth_web/controller_callbacks.ex
Normal file
45
apps/core/lib/auth_web/controller_callbacks.ex
Normal file
|
@ -0,0 +1,45 @@
|
|||
defmodule AuthWeb.Pow.ControllerCallbacks do
|
||||
@moduledoc """
|
||||
Hook into Pow Controllers to provide additional framework feature. In particular,
|
||||
we disconnect any active live views when a user logs out. This will cause the
|
||||
live view to re-connect with the new session environment.
|
||||
"""
|
||||
alias Pow.Extension.Phoenix.ControllerCallbacks
|
||||
alias Plug.Conn
|
||||
|
||||
def before_respond(Pow.Phoenix.SessionController, :create, {:ok, conn}, config) do
|
||||
user = conn.assigns.current_user
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> Conn.put_session(:current_user_id, user.id)
|
||||
|> Conn.put_session(:live_socket_id, "users_sockets:#{user.id}")
|
||||
|
||||
ControllerCallbacks.before_respond(
|
||||
Pow.Phoenix.SessionController,
|
||||
:create,
|
||||
{:ok, conn},
|
||||
config
|
||||
)
|
||||
end
|
||||
|
||||
def before_respond(Pow.Phoenix.SessionController, :delete, {:ok, conn}, config) do
|
||||
live_socket_id = Conn.get_session(conn, :live_socket_id)
|
||||
AppWeb.Endpoint.broadcast(live_socket_id, "disconnect", %{})
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> Conn.delete_session(:live_socket_id)
|
||||
|
||||
ControllerCallbacks.before_respond(
|
||||
Pow.Phoenix.SessionController,
|
||||
:delete,
|
||||
{:ok, conn},
|
||||
config
|
||||
)
|
||||
end
|
||||
|
||||
defdelegate before_respond(controller, action, results, config), to: ControllerCallbacks
|
||||
|
||||
defdelegate before_process(controller, action, results, config), to: ControllerCallbacks
|
||||
end
|
|
@ -1,7 +1,12 @@
|
|||
defmodule Legendary.AuthWeb.Helpers do
|
||||
def has_role?(conn = %Plug.Conn{}, role) do
|
||||
conn
|
||||
|> Pow.Plug.current_user()
|
||||
def current_user(socket = %Phoenix.LiveView.Socket{assigns: %{current_user: user}}), do: user
|
||||
def current_user(socket = %Phoenix.LiveView.Socket{assigns: %{__assigns__: %{current_user: user}}}), do: user
|
||||
def current_user(%Phoenix.LiveView.Socket{}), do: nil
|
||||
def current_user(conn), do: Pow.Plug.current_user(conn)
|
||||
|
||||
def has_role?(conn_or_socket, role) do
|
||||
conn_or_socket
|
||||
|> current_user()
|
||||
|> Legendary.Auth.Roles.has_role?(role)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,11 +7,8 @@ defmodule Legendary.CoreWeb.Helpers do
|
|||
import Phoenix.Controller, only: [get_flash: 2]
|
||||
import Legendary.CoreWeb.ErrorHelpers
|
||||
|
||||
def has_role?(conn = %Plug.Conn{}, role) do
|
||||
conn
|
||||
|> Pow.Plug.current_user()
|
||||
|> Legendary.Auth.Roles.has_role?(role)
|
||||
end
|
||||
defdelegate current_user(a), to: Legendary.AuthWeb.Helpers
|
||||
defdelegate has_role?(a, b), to: Legendary.AuthWeb.Helpers
|
||||
|
||||
def changeset_error_block(changeset) do
|
||||
~E"""
|
||||
|
|
|
@ -150,7 +150,7 @@ defmodule Legendary.Core.MixProject do
|
|||
{:postgrex, ">= 0.0.0"},
|
||||
{:phoenix_html, "~> 2.11"},
|
||||
{:phoenix_live_reload, "~> 1.2", only: :dev},
|
||||
{:phoenix_live_dashboard, "~> 0.2.0"},
|
||||
{:phoenix_live_dashboard, "~> 0.4.0"},
|
||||
{:phoenix_pubsub, "~> 2.0"},
|
||||
{:pow, "~> 1.0.23"},
|
||||
{:telemetry_metrics, "~> 0.4"},
|
||||
|
|
|
@ -40,7 +40,7 @@ config :core, :pow,
|
|||
user: Legendary.Auth.User,
|
||||
repo: Legendary.Core.Repo,
|
||||
extensions: [PowEmailConfirmation, PowPersistentSession, PowResetPassword],
|
||||
controller_callbacks: Pow.Extension.Phoenix.ControllerCallbacks,
|
||||
controller_callbacks: AuthWeb.Pow.ControllerCallbacks,
|
||||
mailer_backend: Legendary.AuthWeb.Pow.Mailer,
|
||||
web_mailer_module: Legendary.AuthWeb,
|
||||
web_module: Legendary.AuthWeb,
|
||||
|
|
10
mix.lock
10
mix.lock
|
@ -27,7 +27,7 @@
|
|||
"ex_prompt": {:hex, :ex_prompt, "0.1.5", "b136642d0962f8ea37b3c9fa185ad1f42c71c3b9c6c3950f0358d7f3d2db2970", [:mix], [], "hexpm", "ad19a404708c9c7b05d36090b2d074ceafbed248a8de1a22d45a05ebe6994b83"},
|
||||
"excoveralls": {:hex, :excoveralls, "0.13.0", "4e1b7cc4e0351d8d16e9be21b0345a7e165798ee5319c7800b9138ce17e0b38e", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "fe2a56c8909564e2e6764765878d7d5e141f2af3bc8ff3b018a68ee2a218fced"},
|
||||
"file_system": {:hex, :file_system, "0.2.8", "f632bd287927a1eed2b718f22af727c5aeaccc9a98d8c2bd7bff709e851dc986", [:mix], [], "hexpm", "97a3b6f8d63ef53bd0113070102db2ce05352ecf0d25390eb8d747c2bde98bca"},
|
||||
"floki": {:hex, :floki, "0.25.0", "b1c9ddf5f32a3a90b43b76f3386ca054325dc2478af020e87b5111c19f2284ac", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "631f4e627c46d5ecd347df5a2accdaf0621c77c3693c5b75a8ad58e84c61f242"},
|
||||
"floki": {:hex, :floki, "0.31.0", "f05ee8a8e6a3ced4e62beeb2c79a63bc8e12ab98fbaaf6e6a3d9b76b1278e23f", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "b05afa372f5c345a5bf240ac25ea1f0f3d5fcfd7490ac0beeb4a203f9444891e"},
|
||||
"fun_with_flags": {:hex, :fun_with_flags, "1.6.0", "507fcbc19374e83d34ba13d63b0816d37af952da1c6592978bbf40dad6a2e671", [:mix], [{:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: true]}, {:redix, "~> 1.0", [hex: :redix, repo: "hexpm", optional: true]}], "hexpm", "96b53f54737906c5a83b5d89922ca1145fda2d50db23b1f619478460b8d5f8d8"},
|
||||
"fun_with_flags_ui": {:hex, :fun_with_flags_ui, "0.7.2", "c8df9e90f92481c014824ab1ff5db7d501ac34ec28a4599b76251ec5a6db0861", [:mix], [{:cowboy, ">= 1.0.0", [hex: :cowboy, repo: "hexpm", optional: true]}, {:fun_with_flags, "~> 1.1", [hex: :fun_with_flags, repo: "hexpm", optional: false]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "99b3635b067304722560ea3d5aab38ae23ea1217366c95ecb6263559488a22f2"},
|
||||
"gen_smtp": {:hex, :gen_smtp, "0.15.0", "9f51960c17769b26833b50df0b96123605a8024738b62db747fece14eb2fbfcc", [:rebar3], [], "hexpm", "29bd14a88030980849c7ed2447b8db6d6c9278a28b11a44cafe41b791205440f"},
|
||||
|
@ -35,7 +35,7 @@
|
|||
"gen_state_machine": {:hex, :gen_state_machine, "2.1.0", "a38b0e53fad812d29ec149f0d354da5d1bc0d7222c3711f3a0bd5aa608b42992", [:mix], [], "hexpm", "ae367038808db25cee2f2c4b8d0531522ea587c4995eb6f96ee73410a60fa06b"},
|
||||
"gettext": {:hex, :gettext, "0.18.2", "7df3ea191bb56c0309c00a783334b288d08a879f53a7014341284635850a6e55", [:mix], [], "hexpm", "f9f537b13d4fdd30f3039d33cb80144c3aa1f8d9698e47d7bcbcc8df93b1f5c5"},
|
||||
"hackney": {:hex, :hackney, "1.16.0", "5096ac8e823e3a441477b2d187e30dd3fff1a82991a806b2003845ce72ce2d84", [:rebar3], [{:certifi, "2.5.2", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.1", [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]}, {:parse_trans, "3.3.0", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.6", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "3bf0bebbd5d3092a3543b783bf065165fa5d3ad4b899b836810e513064134e18"},
|
||||
"html_entities": {:hex, :html_entities, "0.5.1", "1c9715058b42c35a2ab65edc5b36d0ea66dd083767bef6e3edb57870ef556549", [:mix], [], "hexpm", "30efab070904eb897ff05cd52fa61c1025d7f8ef3a9ca250bc4e6513d16c32de"},
|
||||
"html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"},
|
||||
"html_sanitize_ex": {:hex, :html_sanitize_ex, "1.0.1", "2572e7122c78ab7e57b613e7c7f5e42bf9b3c25e430e32f23f1413d86db8a0af", [:mix], [{:mochiweb, "~> 2.12.2", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm", "c334e2835e094fb9c04658bd4cfc7533fa51a8f56f11343c57ab9cb2a01d8613"},
|
||||
"idna": {:hex, :idna, "6.0.1", "1d038fb2e7668ce41fbf681d2c45902e52b3cb9e9c77b55334353b222c2ee50c", [:rebar3], [{:unicode_util_compat, "0.5.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a02c8a1c4fd601215bb0b0324c8a6986749f807ce35f25449ec9e69758708122"},
|
||||
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
|
||||
|
@ -60,9 +60,9 @@
|
|||
"phoenix_ecto": {:hex, :phoenix_ecto, "4.1.0", "a044d0756d0464c5a541b4a0bf4bcaf89bffcaf92468862408290682c73ae50d", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "c5e666a341ff104d0399d8f0e4ff094559b2fde13a5985d4cb5023b2c2ac558b"},
|
||||
"phoenix_html": {:hex, :phoenix_html, "2.14.3", "51f720d0d543e4e157ff06b65de38e13303d5778a7919bcc696599e5934271b8", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "efd697a7fff35a13eeeb6b43db884705cba353a1a41d127d118fda5f90c8e80f"},
|
||||
"phoenix_html_sanitizer": {:hex, :phoenix_html_sanitizer, "1.0.2", "e2c8cfbc83660e362753de127cc957bec3442a8aecdf271fb65a684a906fccf5", [:mix], [{:html_sanitize_ex, "~> 1.0.0", [hex: :html_sanitize_ex, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}], "hexpm", "47aebb08fa954b7ad95f295fb701df9800ee3a489212119c9c6074a65e1e5a10"},
|
||||
"phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.2.6", "1b4e1b7d797386b7f9d70d2af931dc9843a5f2f2423609d22cef1eec4e4dba7d", [:mix], [{:phoenix_html, "~> 2.14.1 or ~> 2.15", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.13.1", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.4.0 or ~> 0.5.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "b20dcad98c4ca63d38a7f5e7a40936e1e8e9da983d3d722b88ae33afb866c9ca"},
|
||||
"phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.4.0", "87990e68b60213d7487e65814046f9a2bed4a67886c943270125913499b3e5c3", [:mix], [{:ecto_psql_extras, "~> 0.4.1 or ~> 0.5", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.14.1 or ~> 2.15", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.15.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.4.0 or ~> 0.5.0 or ~> 0.6.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "8d52149e58188e9e4497cc0d8900ab94d9b66f96998ec38c47c7a4f8f4f50e57"},
|
||||
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.2.4", "940c0344b1d66a2e46eef02af3a70e0c5bb45a4db0bf47917add271b76cd3914", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "38f9308357dea4cc77f247e216da99fcb0224e05ada1469167520bed4cb8cccd"},
|
||||
"phoenix_live_view": {:hex, :phoenix_live_view, "0.13.3", "2186c55cc7c54ca45b97c6f28cfd267d1c61b5f205f3c83533704cd991bdfdec", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.4.17 or ~> 1.5.2", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14", [hex: :phoenix_html, repo: "hexpm", optional: false]}], "hexpm", "c6309a7da2e779cb9cdf2fb603d75f38f49ef324bedc7a81825998bd1744ff8a"},
|
||||
"phoenix_live_view": {:hex, :phoenix_live_view, "0.15.7", "09720b8e5151b3ca8ef739cd7626d4feb987c69ba0b509c9bbdb861d5a365881", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.5.7", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 0.5", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a756cf662420272d0f1b3b908cce5222163b5a95aa9bab404f9d29aff53276e"},
|
||||
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"},
|
||||
"php_serializer": {:hex, :php_serializer, "0.9.2", "59c5fd6bd3096671fd89358fb8229341ac7423b50ad8d45a15213b02ea2edab2", [:mix], [], "hexpm", "34eb835a460944f7fc216773b363c02e7dcf8ac0390c9e9ccdbd92b31a7ca59a"},
|
||||
"plug": {:hex, :plug, "1.11.1", "f2992bac66fdae679453c9e86134a4201f6f43a687d8ff1cd1b2862d53c80259", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "23524e4fefbb587c11f0833b3910bfb414bf2e2534d61928e920f54e3a1b881f"},
|
||||
|
@ -77,7 +77,7 @@
|
|||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
|
||||
"swarm": {:hex, :swarm, "3.4.0", "64f8b30055d74640d2186c66354b33b999438692a91be275bb89cdc7e401f448", [:mix], [{:gen_state_machine, "~> 2.0", [hex: :gen_state_machine, repo: "hexpm", optional: false]}, {:libring, "~> 1.0", [hex: :libring, repo: "hexpm", optional: false]}], "hexpm", "94884f84783fc1ba027aba8fe8a7dae4aad78c98e9f9c76667ec3471585c08c6"},
|
||||
"telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"},
|
||||
"telemetry_metrics": {:hex, :telemetry_metrics, "0.5.0", "1b796e74add83abf844e808564275dfb342bcc930b04c7577ab780e262b0d998", [:mix], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "31225e6ce7a37a421a0a96ec55244386aec1c190b22578bd245188a4a33298fd"},
|
||||
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.0", "da9d49ee7e6bb1c259d36ce6539cd45ae14d81247a2b0c90edf55e2b50507f7b", [:mix], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5cfe67ad464b243835512aa44321cee91faed6ea868d7fb761d7016e02915c3d"},
|
||||
"telemetry_poller": {:hex, :telemetry_poller, "0.5.1", "21071cc2e536810bac5628b935521ff3e28f0303e770951158c73eaaa01e962a", [:rebar3], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4cab72069210bc6e7a080cec9afffad1b33370149ed5d379b81c7c5f0c663fd4"},
|
||||
"timex": {:hex, :timex, "3.6.2", "845cdeb6119e2fef10751c0b247b6c59d86d78554c83f78db612e3290f819bc2", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "26030b46199d02a590be61c2394b37ea25a3664c02fafbeca0b24c972025d47a"},
|
||||
"tzdata": {:hex, :tzdata, "1.0.3", "73470ad29dde46e350c60a66e6b360d3b99d2d18b74c4c349dbebbc27a09a3eb", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a6e1ee7003c4d04ecbd21dd3ec690d4c6662db5d3bbdd7262d53cdf5e7c746c1"},
|
||||
|
|
Loading…
Reference in a new issue