Browse Source

MONSTER: switch to live view for bookmarks

adds a live filter/search box to bookmark index :))
pull/26/head
Inhji Y. 1 year ago
parent
commit
2adb9daf18
  1. 9
      apps/bookmarks/lib/bookmarks.ex
  2. 28
      apps/tomie_web/assets/js/app.js
  3. 3
      apps/tomie_web/assets/package-lock.json
  4. 1
      apps/tomie_web/assets/package.json
  5. 11
      apps/tomie_web/lib/tomie_web.ex
  6. 2
      apps/tomie_web/lib/tomie_web/endpoint.ex
  7. 37
      apps/tomie_web/lib/tomie_web/live/bookmark_live/edit.ex
  8. 27
      apps/tomie_web/lib/tomie_web/live/bookmark_live/index.ex
  9. 34
      apps/tomie_web/lib/tomie_web/live/bookmark_live/new.ex
  10. 23
      apps/tomie_web/lib/tomie_web/live/bookmark_live/show.ex
  11. 9
      apps/tomie_web/lib/tomie_web/router.ex
  12. 1
      apps/tomie_web/lib/tomie_web/templates/bookmark/edit.html.eex
  13. 1
      apps/tomie_web/lib/tomie_web/templates/bookmark/edit.html.leex
  14. 5
      apps/tomie_web/lib/tomie_web/templates/bookmark/form.html.leex
  15. 12
      apps/tomie_web/lib/tomie_web/templates/bookmark/index.html.leex
  16. 1
      apps/tomie_web/lib/tomie_web/templates/bookmark/new.html.eex
  17. 1
      apps/tomie_web/lib/tomie_web/templates/bookmark/new.html.leex
  18. 14
      apps/tomie_web/lib/tomie_web/templates/bookmark/show.html.eex
  19. 13
      apps/tomie_web/lib/tomie_web/templates/bookmark/show.html.leex
  20. 64
      apps/tomie_web/lib/tomie_web/templates/layout/app.html.eex
  21. 1
      apps/tomie_web/lib/tomie_web/templates/layout/live.html.eex
  22. 60
      apps/tomie_web/lib/tomie_web/templates/layout/root.html.eex
  23. 1
      apps/tomie_web/lib/tomie_web/views/bookmark_view.ex
  24. 3
      apps/tomie_web/lib/tomie_web/views/profile_view.ex
  25. 1
      apps/tomie_web/mix.exs
  26. 2
      config/config.exs
  27. 1
      mix.lock

9
apps/bookmarks/lib/bookmarks.ex

@ -45,6 +45,15 @@ defmodule Bookmarks do
)
end
def query_bookmarks(search_string) do
Db.Repo.all(
from b in Bookmark,
select: b,
where: ilike(b.title, ^"%#{search_string}%"),
preload: [:tags]
)
end
@doc """
Registers a visit of the bookmarks url by updating `views` and `viewed_at`
"""

28
apps/tomie_web/assets/js/app.js

@ -3,26 +3,26 @@
// its own CSS file.
import css from "../css/app.css"
// webpack automatically bundles all modules in your
// entry points. Those entry points can be configured
// in "webpack.config.js".
//
// Import dependencies
//
import "phoenix_html"
import {Socket} from "phoenix"
import LiveSocket from "phoenix_live_view"
// Import local files
//
// Local files can be imported directly using relative paths, for example:
// import socket from "./socket"
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}})
const toggleButton = document.querySelector('.theme-toggle')
liveSocket.connect()
toggleButton.addEventListener('click', function (e) {
window.liveSocket = liveSocket
// Theme Switch
const toggleButton = document.querySelector(".theme-toggle")
toggleButton.addEventListener("click", function (e) {
e.preventDefault()
const body = document.querySelector('body')
const body = document.querySelector("body")
const theme = body.dataset.theme
body.dataset.theme = (theme === 'light' ? 'dark' : 'light')
body.dataset.theme = (theme === "light" ? "dark" : "light")
})

3
apps/tomie_web/assets/package-lock.json

@ -5100,6 +5100,9 @@
"phoenix_html": {
"version": "file:../../../deps/phoenix_html"
},
"phoenix_live_view": {
"version": "file:../../../deps/phoenix_live_view"
},
"pify": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",

1
apps/tomie_web/assets/package.json

@ -8,6 +8,7 @@
"dependencies": {
"phoenix": "file:../../../deps/phoenix",
"phoenix_html": "file:../../../deps/phoenix_html",
"phoenix_live_view": "file:../../../deps/phoenix_live_view",
"tailwindcss": "^1.2.0"
},
"devDependencies": {

11
apps/tomie_web/lib/tomie_web.ex

@ -22,11 +22,19 @@ defmodule TomieWeb do
use Phoenix.Controller, namespace: TomieWeb
import Plug.Conn
import TomieWeb.Gettext
import Phoenix.LiveView.Controller
alias TomieWeb.Router.Helpers, as: Routes
alias TomieWeb.Worker
end
end
def live do
quote do
use Phoenix.LiveView
alias TomieWeb.Router.Helpers, as: Routes
end
end
def view do
quote do
use Phoenix.View,
@ -35,6 +43,7 @@ defmodule TomieWeb do
# Import convenience functions from controllers
import Phoenix.Controller, only: [get_flash: 1, get_flash: 2, view_module: 1]
import Phoenix.LiveView.Helpers
# Use all HTML functionality (forms, tags, etc)
use Phoenix.HTML
@ -53,8 +62,10 @@ defmodule TomieWeb do
def router do
quote do
use Phoenix.Router
use Pow.Phoenix.Router
import Plug.Conn
import Phoenix.Controller
import Phoenix.LiveView.Router
end
end

2
apps/tomie_web/lib/tomie_web/endpoint.ex

@ -10,6 +10,8 @@ defmodule TomieWeb.Endpoint do
signing_salt: "bnetjq+s"
]
socket "/live", Phoenix.LiveView.Socket, websocket: [connect_info: [session: @session_options]]
# Serve at "/" the static files from "priv/static" directory.
#
# You should set gzip to true if you are running phx.digest

37
apps/tomie_web/lib/tomie_web/live/bookmark_live/edit.ex

@ -0,0 +1,37 @@
defmodule TomieWeb.BookmarkLive.Edit do
use TomieWeb, :live
alias Bookmarks.Bookmark
alias TomieWeb.{BookmarkLive, BookmarkView}
def render(assigns), do: BookmarkView.render("edit.html", assigns)
def mount(_params, _session, socket), do: {:ok, socket}
def handle_params(%{"id" => id}, _uri, socket) do
{:noreply, socket |> assign(id: id) |> fetch()}
end
def fetch(%{assigns: %{id: id}} = socket) do
bookmark = Bookmarks.get_bookmark!(id)
assign(socket, bookmark: bookmark, changeset: Bookmark.changeset(bookmark))
end
def handle_event("validate", %{"bookmark" => params}, socket) do
changeset =
%Bookmark{}
|> Bookmark.changeset(params)
|> Map.put(:action, :update)
{:noreply, assign(socket, changeset: changeset)}
end
def handle_event("save", %{"bookmark" => params}, socket) do
case Bookmarks.update_bookmark(socket.assigns.bookmark, params) do
{:ok, bookmark} ->
{:noreply,
push_redirect(socket, to: Routes.live_path(socket, BookmarkLive.Show, bookmark))}
{:error, changeset} ->
{:noreply, assign(socket, changeset: changeset)}
end
end
end

27
apps/tomie_web/lib/tomie_web/live/bookmark_live/index.ex

@ -0,0 +1,27 @@
defmodule TomieWeb.BookmarkLive.Index do
use TomieWeb, :live
use Phoenix.HTML
def render(assigns), do: TomieWeb.BookmarkView.render("index.html", assigns)
def mount(_params, _session, socket) do
bookmarks = Bookmarks.list_bookmarks()
{:ok, assign(socket, changeset: changeset(), bookmarks: bookmarks)}
end
def handle_event("search", %{"search" => %{"query" => query}}, socket) do
bookmarks = Bookmarks.query_bookmarks(query)
IO.inspect(query)
{:noreply, assign(socket, bookmarks: bookmarks)}
end
def changeset(attrs \\ %{}) do
types = %{query: :string}
{%{}, types}
|> Ecto.Changeset.cast(attrs, Map.keys(types))
|> Ecto.Changeset.validate_required([:query])
end
end

34
apps/tomie_web/lib/tomie_web/live/bookmark_live/new.ex

@ -0,0 +1,34 @@
defmodule TomieWeb.BookmarkLive.New do
use TomieWeb, :live
alias Bookmarks.Bookmark
alias TomieWeb.{BookmarkLive, BookmarkView}
def render(assigns), do: BookmarkView.render("new.html", assigns)
def mount(_params, _session, socket) do
changeset = Bookmark.changeset(%Bookmark{})
{:ok, assign(socket, changeset: changeset)}
end
def handle_event("validate", %{"bookmark" => params}, socket) do
changeset =
%Bookmark{}
|> Bookmark.changeset(params)
|> Map.put(:action, :insert)
{:noreply, assign(socket, changeset: changeset)}
end
def handle_event("save", %{"bookmark" => params}, socket) do
case Bookmarks.create_bookmark(params) do
{:ok, bookmark} ->
TomieWeb.Worker.run(bookmark)
{:noreply,
push_redirect(socket, to: Routes.live_path(socket, BookmarkLive.Show, bookmark))}
{:error, changeset} ->
{:noreply, assign(socket, changeset: changeset)}
end
end
end

23
apps/tomie_web/lib/tomie_web/live/bookmark_live/show.ex

@ -0,0 +1,23 @@
defmodule TomieWeb.BookmarkLive.Show do
use TomieWeb, :live
alias Bookmarks.Bookmark
alias TomieWeb.{BookmarkLive, BookmarkView}
def render(assigns), do: BookmarkView.render("show.html", assigns)
def mount(_params, _session, socket), do: {:ok, socket}
def handle_params(%{"id" => id}, _uri, socket) do
{:noreply, socket |> assign(id: id) |> fetch()}
end
def fetch(%{assigns: %{id: id}} = socket) do
assign(socket, bookmark: Bookmarks.get_bookmark!(id))
end
def handle_event("delete_bookmark", %{"id" => id}, socket) do
Bookmarks.get_bookmark!(id)
|> Bookmarks.delete_bookmark()
{:noreply, push_redirect(socket, to: Routes.live_path(socket, BookmarkLive.Index))}
end
end

9
apps/tomie_web/lib/tomie_web/router.ex

@ -1,13 +1,13 @@
defmodule TomieWeb.Router do
use TomieWeb, :router
use Pow.Phoenix.Router
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_root_layout, {TomieWeb.LayoutView, :root}
end
pipeline :api do
@ -30,9 +30,12 @@ defmodule TomieWeb.Router do
get "/", PageController, :index
live "/bookmarks", BookmarkLive.Index
live "/bookmarks/new", BookmarkLive.New
live "/bookmarks/:id", BookmarkLive.Show
live "/bookmarks/:id/edit", BookmarkLive.Edit
get "/bookmarks/:id/visit", BookmarkController, :visit
get "/bookmarks/save", BookmarkController, :bookmarklet
resources "/bookmarks", BookmarkController
resources "/tags", TagController

1
apps/tomie_web/lib/tomie_web/templates/bookmark/edit.html.eex

@ -1 +0,0 @@
<%= render "form.html", Map.put(assigns, :action, Routes.bookmark_path(@conn, :update, @bookmark)) %>

1
apps/tomie_web/lib/tomie_web/templates/bookmark/edit.html.leex

@ -0,0 +1 @@
<%= render "form.html", assigns %>

5
apps/tomie_web/lib/tomie_web/templates/bookmark/form.html.eex → apps/tomie_web/lib/tomie_web/templates/bookmark/form.html.leex

@ -1,4 +1,5 @@
<%= form_for @changeset, @action, fn f -> %>
<%= f = form_for @changeset, "#",
[phx_change: :validate, phx_submit: :save ] %>
<fieldset>
<%= label f, :source, "Bookmark Source" %>
<%= url_input f, :source, autofocus: true, required: true %>
@ -34,4 +35,4 @@
</fieldset>
<%= submit "submit" %>
<% end %>
</form>

12
apps/tomie_web/lib/tomie_web/templates/bookmark/index.html.eex → apps/tomie_web/lib/tomie_web/templates/bookmark/index.html.leex

@ -1,17 +1,21 @@
<nav>
<ul>
<li><%= link "Add new Bookmark", to: Routes.bookmark_path(@conn, :new) %></li>
<li><%= live_patch "Add new Bookmark", to: Routes.live_path(@socket, BookmarkLive.New) %></li>
</ul>
</nav>
<form class="search">
<input class="border-none shadow rounded-none text-lg bg-surface-alt text-on-surface focus:text-surface font-bold p-4" type="text" name="query" placeholder="Search...">
<%= f = form_for @changeset, "#", [as: :search, phx_change: :search, class: "search"] %>
<%= text_input f, :query,
class: "border-none shadow rounded-none text-lg bg-surface-alt text-on-surface focus:text-surface font-bold p-4",
placeholder: "Search...",
phx_debounce: 200
%>
</form>
<section class="list">
<%= for bookmark <- @bookmarks do %>
<article class="card">
<%= link to: Routes.bookmark_path(@conn, :show, bookmark), class: "block" do %>
<%= live_patch to: Routes.live_path(@socket, BookmarkLive.Show, bookmark), class: "block" do %>
<h3 class="text-xl">
<%= bookmark.title || bookmark.source %>
</h3>

1
apps/tomie_web/lib/tomie_web/templates/bookmark/new.html.eex

@ -1 +0,0 @@
<%= render "form.html", Map.put(assigns, :action, Routes.bookmark_path(@conn, :create)) %>

1
apps/tomie_web/lib/tomie_web/templates/bookmark/new.html.leex

@ -0,0 +1 @@
<%= render "form.html", assigns %>

14
apps/tomie_web/lib/tomie_web/templates/bookmark/show.html.eex

@ -1,14 +0,0 @@
<nav>
<ul>
<li><%= link "Back", to: Routes.bookmark_path(@conn, :index) %></li>
<li><%= link "Visit URL", to: Routes.bookmark_path(@conn, :visit, @bookmark) %></li>
<li><%= link "Edit", to: Routes.bookmark_path(@conn, :edit, @bookmark) %></li>
<li><%= link "Delete", to: Routes.bookmark_path(@conn, :delete, @bookmark), method: :delete, data: [confirm: "Are you sure?"] %></li>
</ul>
</nav>
<h1><%= @bookmark.title || @bookmark.source %></h1>
<p>
<%= @bookmark.content %>
</p>

13
apps/tomie_web/lib/tomie_web/templates/bookmark/show.html.leex

@ -0,0 +1,13 @@
<nav>
<ul>
<li><%= live_patch "Back", to: Routes.live_path(@socket, BookmarkLive.Index) %></li>
<li><%= live_patch "Edit", to: Routes.live_path(@socket, BookmarkLive.Edit, @bookmark) %></li>
<li><%= link "Delete", to: "#", phx_click: "delete_bookmark", phx_value_id: @bookmark.id %></li>
</ul>
</nav>
<h1><%= @bookmark.title || @bookmark.source %></h1>
<p>
<%= @bookmark.content %>
</p>

64
apps/tomie_web/lib/tomie_web/templates/layout/app.html.eex

@ -1,63 +1 @@
<!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><%= assigns[:page_title] || "Tomie · Phoenix Framework" %></title>
<link rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
<script type="text/javascript" src="<%= Routes.static_path(@conn, "/js/awesomeplete/awesomeplete.js") %>"></script>
<script type="text/javascript" src="<%= Routes.static_path(@conn, "/js/awesomeplete/awesomeplete-util.js") %>"></script>
<%= csrf_meta_tag() %>
</head>
<body class="mt-16 transition duration-500" data-theme="<%= theme(@conn) %>">
<nav role="navigation" id="main">
<ul>
<li>
<%= active_link @conn, to: Routes.page_path(@conn, :index) do %>
<span class="icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M8 20H3V10H0L10 0l10 10h-3v10h-5v-6H8v6z"/>
</svg>
</span>
<% end %>
</li>
<li><%= active_link @conn, "Bookmarks", to: Routes.bookmark_path(@conn, :index) %></li>
<li><%= active_link @conn, "Tags", to: Routes.tag_path(@conn, :index) %></li>
<li class="spacer" />
<li>
<a href="#" class="theme-toggle">
<span class="icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M7 13.33a7 7 0 1 1 6 0V16H7v-2.67zM7 17h6v1.5c0 .83-.67 1.5-1.5 1.5h-3A1.5 1.5 0 0 1 7 18.5V17zm2-5.1V14h2v-2.1a5 5 0 1 0-2 0z"/>
</svg>
</span>
</a>
</li>
<%= unless Pow.Plug.current_user(@conn) do %>
<li><%= active_link @conn, "Register", to: Routes.pow_registration_path(@conn, :new) %></li>
<li><%= active_link @conn, "Sign in", to: Routes.pow_session_path(@conn, :new) %></li>
<% else %>
<li>
<%= active_link @conn, to: Routes.profile_path(@conn, :show) do %>
<span class="icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M5 5a5 5 0 0 1 10 0v2A5 5 0 0 1 5 7V5zM0 16.68A19.9 19.9 0 0 1 10 14c3.64 0 7.06.97 10 2.68V20H0v-3.32z"/>
</svg>
</span>
<% end %>
</li>
<% end %>
</ul>
</nav>
<section class="alerts">
<p class="info" role="alert"><%= get_flash(@conn, :info) %></p>
<p class="error" role="alert"><%= get_flash(@conn, :error) %></p>
</section>
<main role="main" class="px-0 py-6 sm:p-6">
<%= render @view_module, @view_template, assigns %>
</main>
<script type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
</body>
</html>
<%= render @view_module, @view_template, assigns %>

1
apps/tomie_web/lib/tomie_web/templates/layout/live.html.eex

@ -0,0 +1 @@
<h1>Live Layout!!!</h1>

60
apps/tomie_web/lib/tomie_web/templates/layout/root.html.eex

@ -0,0 +1,60 @@
<!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><%= assigns[:page_title] || "Tomie · Phoenix Framework" %></title>
<link rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
<script type="text/javascript" src="<%= Routes.static_path(@conn, "/js/awesomeplete/awesomeplete.js") %>"></script>
<script type="text/javascript" src="<%= Routes.static_path(@conn, "/js/awesomeplete/awesomeplete-util.js") %>"></script>
<%= csrf_meta_tag() %>
</head>
<body class="mt-16 transition duration-500" data-theme="<%= theme(@conn) %>">
<nav role="navigation" id="main">
<ul>
<li>
<%= active_link @conn, to: Routes.page_path(@conn, :index) do %>
<span class="icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M8 20H3V10H0L10 0l10 10h-3v10h-5v-6H8v6z"/>
</svg>
</span>
<% end %>
</li>
<li><%= active_link @conn, "Bookmarks", to: Routes.live_path(TomieWeb.Endpoint, TomieWeb.BookmarkLive.Index) %></li>
<li><%= active_link @conn, "Tags", to: Routes.tag_path(@conn, :index) %></li>
<li class="spacer" />
<li>
<a href="#" class="theme-toggle">
<span class="icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M7 13.33a7 7 0 1 1 6 0V16H7v-2.67zM7 17h6v1.5c0 .83-.67 1.5-1.5 1.5h-3A1.5 1.5 0 0 1 7 18.5V17zm2-5.1V14h2v-2.1a5 5 0 1 0-2 0z"/>
</svg>
</span>
</a>
</li>
<%= unless Pow.Plug.current_user(@conn) do %>
<li><%= active_link @conn, "Register", to: Routes.pow_registration_path(@conn, :new) %></li>
<li><%= active_link @conn, "Sign in", to: Routes.pow_session_path(@conn, :new) %></li>
<% else %>
<li>
<%= active_link @conn, to: Routes.profile_path(@conn, :show) do %>
<span class="icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M5 5a5 5 0 0 1 10 0v2A5 5 0 0 1 5 7V5zM0 16.68A19.9 19.9 0 0 1 10 14c3.64 0 7.06.97 10 2.68V20H0v-3.32z"/>
</svg>
</span>
<% end %>
</li>
<% end %>
</ul>
</nav>
<main role="main" class="px-0 py-6 sm:p-6">
<%= @inner_content %>
</main>
<script type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
</body>
</html>

1
apps/tomie_web/lib/tomie_web/views/bookmark_view.ex

@ -1,3 +1,4 @@
defmodule TomieWeb.BookmarkView do
use TomieWeb, :view
alias TomieWeb.BookmarkLive
end

3
apps/tomie_web/lib/tomie_web/views/profile_view.ex

@ -2,7 +2,8 @@ defmodule TomieWeb.ProfileView do
use TomieWeb, :view
def bookmarklet(conn) do
url = Routes.bookmark_url(conn, :bookmarklet)
# url = Routes.bookmark_url(conn, :new)
url = "dummy.url"
user = Pow.Plug.current_user(conn)
"""

1
apps/tomie_web/mix.exs

@ -43,6 +43,7 @@ defmodule TomieWeb.MixProject do
{:phoenix_ecto, "~> 4.0"},
{:phoenix_html, "~> 2.11"},
{:phoenix_live_reload, "~> 1.2", only: :dev},
{:phoenix_live_view, "~> 0.11.1"},
{:phoenix_form_awesomplete, "~> 0.1"},
{:phoenix_active_link, "~> 0.3.0"},
{:gettext, "~> 0.11"},

2
config/config.exs

@ -26,7 +26,7 @@ config :tomie_web, TomieWeb.Endpoint,
secret_key_base: "vA2gj8nBFMrN/nH0bjo09DfxDovTsbUZJbpnsawqXsTneL/F0nWEY5PfY5uptNra",
render_errors: [view: TomieWeb.ErrorView, accepts: ~w(html json)],
pubsub: [name: TomieWeb.PubSub, adapter: Phoenix.PubSub.PG2],
live_view: [signing_salt: "kRH3u6Gz"]
live_view: [signing_salt: "La8TeKsJi1aZt2Bhp8vXfx9HOOFpP/JY"]
config :tomie_web, :pow,
user: Users.User,

1
mix.lock

@ -41,6 +41,7 @@
"phoenix_form_awesomplete": {:hex, :phoenix_form_awesomplete, "0.1.5", "d09aade160b584e3428e1e095645482396f17bddda4f566f1118f12d2598d11c", [:mix], [{:phoenix_html, "~> 2.10", [hex: :phoenix_html, repo: "hexpm", optional: false]}], "hexpm", "acef2dbc638b5bcad92c11e41eb2b55d71f2596741a2f936717b8472196456ec"},
"phoenix_html": {:hex, :phoenix_html, "2.14.1", "7dabafadedb552db142aacbd1f11de1c0bbaa247f90c449ca549d5e30bbc66b4", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "536d5200ad37fecfe55b3241d90b7a8c3a2ca60cd012fc065f776324fa9ab0a9"},
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.2.1", "274a4b07c4adbdd7785d45a8b0bb57634d0b4f45b18d2c508b26c0344bd59b8f", [: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", "41b4103a2fa282cfd747d377233baf213c648fdcc7928f432937676532490eee"},
"phoenix_live_view": {:hex, :phoenix_live_view, "0.11.1", "c9aadf90332f713f3b9cf7ba48883db579eaa24d862adc7ac11a45e58d5efa3c", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.4.16", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14", [hex: :phoenix_html, repo: "hexpm", optional: false]}], "hexpm", "2408e31fc0f355f51e3f3621649fef58fadc6f13a53bb539f41f88b493014456"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.2", "496c303bdf1b2e98a9d26e89af5bba3ab487ba3a3735f74bf1f4064d2a845a3e", [:mix], [], "hexpm", "1f13f9f0f3e769a667a6b6828d29dec37497a082d195cc52dbef401a9b69bf38"},
"plug": {:hex, :plug, "1.10.0", "6508295cbeb4c654860845fb95260737e4a8838d34d115ad76cd487584e2fc4d", [: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: true]}], "hexpm", "422a9727e667be1bf5ab1de03be6fa0ad67b775b2d84ed908f3264415ef29d4a"},
"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", "7d722581ce865a237e14da6d946f92704101740a256bd13ec91e63c0b122fc70"},

Loading…
Cancel
Save