Begin implenting Places using LocationIQ
This commit is contained in:
parent
bbf526d6a8
commit
5ca34c2b6f
@ -12,12 +12,12 @@ defmodule Friends.Friend do
|
|||||||
field(:nickname, :string)
|
field(:nickname, :string)
|
||||||
field(:born, :date)
|
field(:born, :date)
|
||||||
field(:phone, :string)
|
field(:phone, :string)
|
||||||
field(:address, :string)
|
|
||||||
field(:email, :string)
|
field(:email, :string)
|
||||||
field(:slug, :string)
|
field(:slug, :string)
|
||||||
field(:memories, {:array, :string})
|
field(:memories, {:array, :string})
|
||||||
|
|
||||||
belongs_to :user, Friends.Accounts.User, foreign_key: :user_id
|
belongs_to :user, Friends.Accounts.User, foreign_key: :user_id
|
||||||
|
belongs_to :address, Friends.Places.Place, foreign_key: :address_id
|
||||||
|
|
||||||
many_to_many(
|
many_to_many(
|
||||||
:relationships,
|
:relationships,
|
||||||
@ -52,7 +52,7 @@ defmodule Friends.Friend do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def all() do
|
def all() do
|
||||||
preloads = [:relationships, :reverse_relationships, :user]
|
preloads = [:relationships, :reverse_relationships, :user, :address]
|
||||||
@repo.all(from(f in Friends.Friend, preload: ^preloads))
|
@repo.all(from(f in Friends.Friend, preload: ^preloads))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ defmodule Friends.Friend do
|
|||||||
@repo.one(
|
@repo.one(
|
||||||
from(f in Friend,
|
from(f in Friend,
|
||||||
where: f.slug == ^slug,
|
where: f.slug == ^slug,
|
||||||
preload: [:relationships, :reverse_relationships]
|
preload: [:relationships, :reverse_relationships, :address]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
@ -74,7 +74,7 @@ defmodule Friends.Friend do
|
|||||||
@repo.one(
|
@repo.one(
|
||||||
from(f in Friend,
|
from(f in Friend,
|
||||||
where: f.id == ^id,
|
where: f.id == ^id,
|
||||||
preload: [:relationships, :reverse_relationships]
|
preload: [:relationships, :reverse_relationships, :address]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
@ -95,10 +95,9 @@ defmodule Friends.Friend do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update(params) do
|
def update(params) do
|
||||||
{:ok,
|
Friend.get_by_id(params.id |> String.to_integer())
|
||||||
Friend.get_by_id(params.id |> String.to_integer())
|
|> Friend.changeset(params)
|
||||||
|> Friend.changeset(params)
|
|> Map.put(:action, :update)
|
||||||
|> Map.put(:action, :update)}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def commit(changeset) do
|
def commit(changeset) do
|
||||||
@ -193,11 +192,12 @@ defmodule Friends.Friend do
|
|||||||
%Friends.Friend{
|
%Friends.Friend{
|
||||||
relationships: %Ecto.Association.NotLoaded{},
|
relationships: %Ecto.Association.NotLoaded{},
|
||||||
reverse_relationships: %Ecto.Association.NotLoaded{},
|
reverse_relationships: %Ecto.Association.NotLoaded{},
|
||||||
user: %Ecto.Association.NotLoaded{}
|
user: %Ecto.Association.NotLoaded{},
|
||||||
|
address: %Ecto.Association.NotLoaded{}
|
||||||
} = model
|
} = model
|
||||||
) do
|
) do
|
||||||
model
|
model
|
||||||
|> @repo.preload([:user, :relationships, :reverse_relationships])
|
|> @repo.preload([:user, :relationships, :reverse_relationships, :address])
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_preloads(%Friends.Friend{} = friend), do: friend
|
def load_preloads(%Friends.Friend{} = friend), do: friend
|
||||||
|
|||||||
61
friends/lib/friends/places/place.ex
Normal file
61
friends/lib/friends/places/place.ex
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
defmodule Friends.Places.Place do
|
||||||
|
use Ecto.Schema
|
||||||
|
import Ecto.Query
|
||||||
|
import Helpers
|
||||||
|
|
||||||
|
@repo Friends.Repo
|
||||||
|
|
||||||
|
schema "places" do
|
||||||
|
field(:name, :string)
|
||||||
|
field(:type, :string)
|
||||||
|
field(:latlon, {:array, :float})
|
||||||
|
field(:zoom, :integer)
|
||||||
|
|
||||||
|
has_many(:events, Friends.Event)
|
||||||
|
has_many(:friends, Friends.Friend)
|
||||||
|
end
|
||||||
|
|
||||||
|
def new(place_name, opts \\ nil) do
|
||||||
|
{:ok, place} =
|
||||||
|
@repo.insert(%Friends.Places.Place{
|
||||||
|
name: place_name,
|
||||||
|
type: opts[:type]
|
||||||
|
})
|
||||||
|
|
||||||
|
place
|
||||||
|
end
|
||||||
|
|
||||||
|
def get(place_name) do
|
||||||
|
@repo.one(
|
||||||
|
from(p in Place,
|
||||||
|
where: p.name == ^place_name,
|
||||||
|
preload: [:events]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_or_new(name, opts \\ nil) do
|
||||||
|
case get(name) do
|
||||||
|
nil -> new(name, opts)
|
||||||
|
place -> place
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_by_slug(slug) do
|
||||||
|
name = slug |> from_slug
|
||||||
|
|
||||||
|
@repo.one(
|
||||||
|
from(p in Place,
|
||||||
|
where: p.name == ^name,
|
||||||
|
preload: [:events]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def changeset(place, params \\ %{}) do
|
||||||
|
place
|
||||||
|
|> Ecto.Changeset.cast(params, [:name, :type, :latlon, :zoom])
|
||||||
|
|> Ecto.Changeset.validate_required([:name])
|
||||||
|
|> Ecto.Changeset.unique_constraint(:name)
|
||||||
|
end
|
||||||
|
end
|
||||||
27
friends/lib/friends/places/search.ex
Normal file
27
friends/lib/friends/places/search.ex
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
defmodule Friends.Places.Search do
|
||||||
|
def api_key, do: "pk.7c4a6f4bf061fd4a9af9663132c58af3"
|
||||||
|
|
||||||
|
def viewbox(region) do
|
||||||
|
[lat_min, lat_max, lon_min, lon_max] = region |> Enum.map(&String.to_float/1)
|
||||||
|
|
||||||
|
[
|
||||||
|
lat_min - 1,
|
||||||
|
lat_max + 1,
|
||||||
|
lon_min - 1,
|
||||||
|
lon_max + 1
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def query(str, region \\ nil) do
|
||||||
|
viewbox =
|
||||||
|
if region do
|
||||||
|
viewbox(query(region))
|
||||||
|
end
|
||||||
|
|
||||||
|
url = "https://us1.locationiq.com/v1/search?key=#{api_key()}&q=#{str}&format=json#{viewbox}"
|
||||||
|
|
||||||
|
response = HTTPoison.get!(url)
|
||||||
|
results = Poison.decode!(response.body)
|
||||||
|
results
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -10,7 +10,8 @@ defmodule FriendsWeb.Endpoint do
|
|||||||
signing_salt: "jNBoklme"
|
signing_salt: "jNBoklme"
|
||||||
]
|
]
|
||||||
|
|
||||||
socket "/live", Phoenix.LiveView.Socket, websocket: [connect_info: [session: @session_options]]
|
socket "/live", Phoenix.LiveView.Socket,
|
||||||
|
websocket: [connect_info: [:peer_data, session: @session_options]]
|
||||||
|
|
||||||
# Serve at "/" the static files from "priv/static" directory.
|
# Serve at "/" the static files from "priv/static" directory.
|
||||||
#
|
#
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
defmodule FriendsWeb.FriendsLive.Components do
|
defmodule FriendsWeb.FriendsLive.Components do
|
||||||
use FriendsWeb, :live_view
|
use FriendsWeb, :live_component
|
||||||
use Phoenix.HTML
|
use Phoenix.HTML
|
||||||
import Helpers
|
import Helpers
|
||||||
alias Friends.Friend
|
alias Friends.Friend
|
||||||
@ -25,6 +25,19 @@ defmodule FriendsWeb.FriendsLive.Components do
|
|||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def edit_menu(assigns) do
|
||||||
|
~H"""
|
||||||
|
<div class="hidden sm:tabs sm:mb-8">
|
||||||
|
<%= for page <- [:overview, :timeline, :relationships] do %>
|
||||||
|
<% is_active = if(page == @live_action) do "tab-active" end %>
|
||||||
|
<.link patch={Routes.friends_edit_path(FriendsWeb.Endpoint, page, @friend.slug)} class={"font-bold sm:tab-lg flex-grow no-underline tab tab-lifted #{is_active}"}>
|
||||||
|
<%= page |> to_string |> :string.titlecase() %>
|
||||||
|
</.link>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
def show_page(:main, assigns), do: show_page(:overview, %{assigns | live_action: :overview})
|
def show_page(:main, assigns), do: show_page(:overview, %{assigns | live_action: :overview})
|
||||||
|
|
||||||
def show_page(:overview, assigns) do
|
def show_page(:overview, assigns) do
|
||||||
@ -109,6 +122,8 @@ defmodule FriendsWeb.FriendsLive.Components do
|
|||||||
|
|
||||||
def edit_page(:overview, assigns) do
|
def edit_page(:overview, assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
|
<%= @peer_data.address |> Tuple.to_list |> Enum.join(".") %>
|
||||||
|
|
||||||
<.form
|
<.form
|
||||||
for={@changeset}
|
for={@changeset}
|
||||||
let={f}
|
let={f}
|
||||||
@ -155,6 +170,13 @@ defmodule FriendsWeb.FriendsLive.Components do
|
|||||||
<div class="min-w-fit flex place-items-center mr-4"><%= error_tag f, :phone %></div>
|
<div class="min-w-fit flex place-items-center mr-4"><%= error_tag f, :phone %></div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="flex flex-row gap-x-6">
|
||||||
|
<strong class="md:text-xl w-20 md:w-28 shrink-0 text-right">Address:</strong>
|
||||||
|
<div class="flex flex-col h-16">
|
||||||
|
<%= text_input f, :address_query, class: "input input-primary input-sm md:input-md", phx_throttle: "500", value: @address_query %>
|
||||||
|
<%= hidden_input f, :address_id, value: 0 %>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="form-control flex flex-row gap-x-4 md:justify-end mb-4 md:w-1/2">
|
<div class="form-control flex flex-row gap-x-4 md:justify-end mb-4 md:w-1/2">
|
||||||
@ -180,7 +202,11 @@ defmodule FriendsWeb.FriendsLive.Components do
|
|||||||
|
|
||||||
def edit_page(:relationships, assigns) do
|
def edit_page(:relationships, assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<%= Components.header(assigns) %>
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit_page(:timeline, assigns) do
|
||||||
|
~H"""
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
126
friends/lib/friends_web/live/edit.ex
Normal file
126
friends/lib/friends_web/live/edit.ex
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
defmodule FriendsWeb.FriendsLive.Edit do
|
||||||
|
use FriendsWeb, :live_view
|
||||||
|
import FriendsWeb.LiveHelpers
|
||||||
|
import FriendsWeb.FriendsLive.Components
|
||||||
|
import Helpers
|
||||||
|
import Helpers.Names
|
||||||
|
|
||||||
|
alias Friends.{Friend, Places}
|
||||||
|
|
||||||
|
def mount(%{"slug" => slug} = _attrs, token, socket) do
|
||||||
|
live_action = socket.assigns.live_action || false
|
||||||
|
|
||||||
|
friend = Friend.get_by_slug(slug)
|
||||||
|
editable = friend |> Friend.can_be_edited_by(socket.assigns[:current_user])
|
||||||
|
|
||||||
|
# address_viewbox = Places.Search.query()
|
||||||
|
|
||||||
|
if(live_action) do
|
||||||
|
{:ok,
|
||||||
|
socket
|
||||||
|
|> assign(:live_action, live_action)
|
||||||
|
|> assign_current_user(token |> Map.get("user_token"))
|
||||||
|
|> assign(:friend, friend)
|
||||||
|
|> title(friend.name <> " - " <> (live_action |> titlecase))
|
||||||
|
|> assign(:changeset, %Friend{} |> Friend.changeset())
|
||||||
|
|> assign(:action, editable)
|
||||||
|
|> assign(:address_query, nil)
|
||||||
|
|> assign(:peer_data, get_connect_info(socket, :peer_data))}
|
||||||
|
else
|
||||||
|
{:ok, socket |> redirect(to: Routes.friends_show_path(socket, :overview, friend.slug))}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_params(%{"slug" => slug} = attrs, _url, socket) do
|
||||||
|
live_action = socket.assigns.live_action || false
|
||||||
|
|
||||||
|
friend = Friend.get_by_slug(slug)
|
||||||
|
editable = friend |> Friend.can_be_edited_by(socket.assigns[:current_user])
|
||||||
|
|
||||||
|
{:noreply,
|
||||||
|
socket
|
||||||
|
|> assign_friend(friend)
|
||||||
|
|> assign(:live_action, live_action)
|
||||||
|
|> title(friend.name <> " - " <> (live_action |> titlecase))
|
||||||
|
|> assign(:editable, editable)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_event("validate", %{"friend" => form_params}, %{assigns: %{friend: friend}} = socket) do
|
||||||
|
id = form_params["id"]
|
||||||
|
name = form_params["name"]
|
||||||
|
nickname = form_params["nickname"]
|
||||||
|
born = form_params["born"]
|
||||||
|
email = form_params["email"]
|
||||||
|
phone = form_params["phone"] |> format_phone
|
||||||
|
address_query = form_params["address_query"]
|
||||||
|
|
||||||
|
new_params = %{
|
||||||
|
id: id,
|
||||||
|
name: name,
|
||||||
|
nickname: nickname,
|
||||||
|
slug: friend.slug,
|
||||||
|
born: born,
|
||||||
|
phone: phone,
|
||||||
|
email: email
|
||||||
|
}
|
||||||
|
|
||||||
|
changeset =
|
||||||
|
%Friend{}
|
||||||
|
|> Friend.changeset(new_params)
|
||||||
|
|> Map.put(:action, :validate)
|
||||||
|
|
||||||
|
{
|
||||||
|
:noreply,
|
||||||
|
socket
|
||||||
|
|> assign(:changeset, changeset)
|
||||||
|
|> assign_friend(friend |> struct(new_params), changeset)
|
||||||
|
|> assign(:address_query, address_query)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Handle form saving
|
||||||
|
def handle_event(
|
||||||
|
"save",
|
||||||
|
%{"friend" => form_params},
|
||||||
|
%{assigns: %{changeset: changeset}} = socket
|
||||||
|
) do
|
||||||
|
name = form_params["name"]
|
||||||
|
nickname = form_params["nickname"]
|
||||||
|
born = form_params["born"]
|
||||||
|
email = form_params["email"]
|
||||||
|
phone = form_params["phone"] |> format_phone
|
||||||
|
id = form_params["id"]
|
||||||
|
|
||||||
|
new_params = %{
|
||||||
|
id: id,
|
||||||
|
name: name,
|
||||||
|
nickname: nickname,
|
||||||
|
slug: name |> to_slug,
|
||||||
|
born: born,
|
||||||
|
phone: phone,
|
||||||
|
email: email
|
||||||
|
}
|
||||||
|
|
||||||
|
updated_friend = Friend.create_or_update(new_params)
|
||||||
|
new_changeset = updated_friend |> Friend.changeset()
|
||||||
|
|
||||||
|
{
|
||||||
|
:noreply,
|
||||||
|
socket
|
||||||
|
|> put_flash(:info, "Saved #{updated_friend |> first_name}!")
|
||||||
|
|> assign(:new_friend, new_changeset)
|
||||||
|
|> assign(:friend, updated_friend)
|
||||||
|
|> push_patch(to: "/friend/#{updated_friend.slug}")
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Handle deleting a friend
|
||||||
|
def handle_event("delete", %{"friend_id" => friend_id}, socket) do
|
||||||
|
friend = Friend.get_by_id(friend_id)
|
||||||
|
|
||||||
|
{:noreply,
|
||||||
|
socket
|
||||||
|
|> put_flash(:error, "Deleted '#{friend.name}'.")
|
||||||
|
|> push_navigate(to: "/")}
|
||||||
|
end
|
||||||
|
end
|
||||||
6
friends/lib/friends_web/live/edit.html.heex
Normal file
6
friends/lib/friends_web/live/edit.html.heex
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<section class="row">
|
||||||
|
<article class="column prose">
|
||||||
|
<%= edit_menu(assigns) %>
|
||||||
|
<%= edit_page(@live_action, assigns) %>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
@ -28,84 +28,4 @@ defmodule FriendsWeb.FriendsLive.Friend do
|
|||||||
|> assign_friend(friend)
|
|> assign_friend(friend)
|
||||||
|> assign(:action, Routes.friends_path(socket, :create))}
|
|> assign(:action, Routes.friends_path(socket, :create))}
|
||||||
end
|
end
|
||||||
|
|
||||||
# Handle form validation
|
|
||||||
def handle_event("validate", %{"friend" => form_params}, %{assigns: %{friend: friend}} = socket) do
|
|
||||||
id = form_params["id"]
|
|
||||||
name = form_params["name"]
|
|
||||||
nickname = form_params["nickname"]
|
|
||||||
born = form_params["born"]
|
|
||||||
email = form_params["email"]
|
|
||||||
phone = form_params["phone"] |> format_phone
|
|
||||||
|
|
||||||
new_params = %{
|
|
||||||
id: id,
|
|
||||||
name: name,
|
|
||||||
nickname: nickname,
|
|
||||||
slug: friend.slug,
|
|
||||||
born: born,
|
|
||||||
phone: phone,
|
|
||||||
email: email
|
|
||||||
}
|
|
||||||
|
|
||||||
changeset =
|
|
||||||
%Friend{}
|
|
||||||
|> Friend.changeset(new_params)
|
|
||||||
|> Map.put(:action, :validate)
|
|
||||||
|
|
||||||
{
|
|
||||||
:noreply,
|
|
||||||
socket
|
|
||||||
|> assign(:changeset, changeset)
|
|
||||||
|> assign_friend(friend |> struct(new_params), changeset)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
# Handle form saving
|
|
||||||
def handle_event(
|
|
||||||
"save",
|
|
||||||
%{"friend" => form_params},
|
|
||||||
%{assigns: %{changeset: changeset}} = socket
|
|
||||||
) do
|
|
||||||
name = form_params["name"]
|
|
||||||
nickname = form_params["nickname"]
|
|
||||||
born = form_params["born"]
|
|
||||||
email = form_params["email"]
|
|
||||||
phone = form_params["phone"] |> format_phone
|
|
||||||
id = form_params["id"]
|
|
||||||
|
|
||||||
new_params = %{
|
|
||||||
id: id,
|
|
||||||
name: name,
|
|
||||||
nickname: nickname,
|
|
||||||
slug: name |> to_slug,
|
|
||||||
born: born,
|
|
||||||
phone: phone,
|
|
||||||
email: email
|
|
||||||
}
|
|
||||||
|
|
||||||
updated_friend = Friend.create_or_update(new_params)
|
|
||||||
new_changeset = updated_friend |> Friend.changeset()
|
|
||||||
|
|
||||||
{
|
|
||||||
:noreply,
|
|
||||||
socket
|
|
||||||
|> put_flash(:info, "Saved #{updated_friend |> first_name}!")
|
|
||||||
|> assign(:new_friend, new_changeset)
|
|
||||||
|> assign(:friend, updated_friend)
|
|
||||||
|> push_patch(to: "/friend/#{updated_friend.slug}")
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
# Handle deleting a friend
|
|
||||||
def handle_event("delete", %{"friend_id" => friend_id}, socket) do
|
|
||||||
friend = Friend.get_by_id(friend_id)
|
|
||||||
|
|
||||||
{:noreply,
|
|
||||||
socket
|
|
||||||
|> put_flash(:error, "Deleted '#{friend.name}'.")
|
|
||||||
|> push_navigate(to: "/")}
|
|
||||||
end
|
|
||||||
|
|
||||||
# Route to the right sub-template in Components/Components.ex
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
defmodule FriendsWeb.FriendsLive.Show do
|
defmodule FriendsWeb.FriendsLive.Show do
|
||||||
use FriendsWeb, :live_view
|
use FriendsWeb, :live_view
|
||||||
import FriendsWeb.LiveHelpers
|
import FriendsWeb.LiveHelpers
|
||||||
|
import FriendsWeb.FriendsLive.Components
|
||||||
alias Friends.Friend
|
alias Friends.Friend
|
||||||
alias FriendsWeb.FriendsLive.Components
|
|
||||||
|
|
||||||
def mount(%{"slug" => slug} = _attrs, token, socket) do
|
def mount(%{"slug" => slug} = _attrs, token, socket) do
|
||||||
live_action = socket.assigns.live_action || false
|
live_action = socket.assigns.live_action || false
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
<section class="row">
|
<section class="row">
|
||||||
<article class="column prose">
|
<article class="column prose">
|
||||||
<%= Components.menu(assigns) %>
|
<%= menu(assigns) %>
|
||||||
<%= Components.header(assigns) %>
|
<%= header(assigns) %>
|
||||||
<%= Components.show_page(@live_action, assigns) %>
|
<%= show_page(@live_action, assigns) %>
|
||||||
|
|
||||||
<%= if @editable do %>
|
<%= if @editable do %>
|
||||||
<div class="form-control flex flex-row mb-4">
|
<div class="form-control flex flex-row mb-4">
|
||||||
<.link patch={Routes.friends_edit_path(FriendsWeb.Endpoint, :overview, @friend.slug)} class="btn btn-block md:btn-wide text-white">edit</.link>
|
<.link navigate={Routes.friends_edit_path(FriendsWeb.Endpoint, :overview, @friend.slug)} class="btn btn-block md:btn-wide text-white">edit</.link>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</article>
|
</article>
|
||||||
|
|||||||
@ -92,9 +92,11 @@ defmodule FriendsWeb.Router do
|
|||||||
# View-only modes (don't require being logged in and having a profile)
|
# View-only modes (don't require being logged in and having a profile)
|
||||||
scope "/friends", FriendsWeb do
|
scope "/friends", FriendsWeb do
|
||||||
pipe_through [:browser]
|
pipe_through [:browser]
|
||||||
|
|
||||||
get "/", FriendsController, :index
|
get "/", FriendsController, :index
|
||||||
|
end
|
||||||
|
|
||||||
|
scope "/friend", FriendsWeb do
|
||||||
|
pipe_through [:browser]
|
||||||
live "/:slug", FriendsLive.Show
|
live "/:slug", FriendsLive.Show
|
||||||
live "/:slug/overview", FriendsLive.Show, :overview
|
live "/:slug/overview", FriendsLive.Show, :overview
|
||||||
live "/:slug/timeline", FriendsLive.Show, :timeline
|
live "/:slug/timeline", FriendsLive.Show, :timeline
|
||||||
@ -102,7 +104,7 @@ defmodule FriendsWeb.Router do
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Edit modes (require being logged in and having a profile)
|
# Edit modes (require being logged in and having a profile)
|
||||||
scope "/update/", FriendsWeb do
|
scope "/friend/update/", FriendsWeb do
|
||||||
pipe_through [:browser, :require_authenticated_user, :capture_profile]
|
pipe_through [:browser, :require_authenticated_user, :capture_profile]
|
||||||
|
|
||||||
live "/:slug/overview", FriendsLive.Edit, :overview
|
live "/:slug/overview", FriendsLive.Edit, :overview
|
||||||
|
|||||||
@ -55,7 +55,9 @@ defmodule Friends.MixProject do
|
|||||||
{:earmark, "~> 1.4"},
|
{:earmark, "~> 1.4"},
|
||||||
{:html_sanitize_ex, "~> 1.3"},
|
{:html_sanitize_ex, "~> 1.3"},
|
||||||
{:yamerl, github: "yakaz/yamerl"},
|
{:yamerl, github: "yakaz/yamerl"},
|
||||||
{:iamvery, "~> 0.6"}
|
{:iamvery, "~> 0.6"},
|
||||||
|
{:httpoison, "~> 1.8"},
|
||||||
|
{:poison, "~> 5.0"}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
"hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"},
|
"hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"},
|
||||||
"html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"},
|
"html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"},
|
||||||
"html_sanitize_ex": {:hex, :html_sanitize_ex, "1.4.2", "c479398b6de798c03eb5d04a0a9a9159d73508f83f6590a00b8eacba3619cf4c", [:mix], [{:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm", "aef6c28585d06a9109ad591507e508854c5559561f950bbaea773900dd369b0e"},
|
"html_sanitize_ex": {:hex, :html_sanitize_ex, "1.4.2", "c479398b6de798c03eb5d04a0a9a9159d73508f83f6590a00b8eacba3619cf4c", [:mix], [{:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm", "aef6c28585d06a9109ad591507e508854c5559561f950bbaea773900dd369b0e"},
|
||||||
|
"httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"},
|
||||||
"iamvery": {:hex, :iamvery, "0.6.0", "6df5a753023cb4ea281f96f1c311d9af39e5e0d8328e2db5fa9923036ea3ddc0", [:mix], [], "hexpm", "6c408c7b1e4dc1c8736470f88a40177559b2dd898f27cf250574e87585f9a925"},
|
"iamvery": {:hex, :iamvery, "0.6.0", "6df5a753023cb4ea281f96f1c311d9af39e5e0d8328e2db5fa9923036ea3ddc0", [:mix], [], "hexpm", "6c408c7b1e4dc1c8736470f88a40177559b2dd898f27cf250574e87585f9a925"},
|
||||||
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
|
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
|
||||||
"jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
|
"jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
|
||||||
@ -41,6 +42,7 @@
|
|||||||
"plug": {:hex, :plug, "1.13.6", "187beb6b67c6cec50503e940f0434ea4692b19384d47e5fdfd701e93cadb4cc2", [:mix], [{:mime, "~> 1.0 or ~> 2.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.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "02b9c6b9955bce92c829f31d6284bf53c591ca63c4fb9ff81dfd0418667a34ff"},
|
"plug": {:hex, :plug, "1.13.6", "187beb6b67c6cec50503e940f0434ea4692b19384d47e5fdfd701e93cadb4cc2", [:mix], [{:mime, "~> 1.0 or ~> 2.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.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "02b9c6b9955bce92c829f31d6284bf53c591ca63c4fb9ff81dfd0418667a34ff"},
|
||||||
"plug_cowboy": {:hex, :plug_cowboy, "2.5.2", "62894ccd601cf9597e2c23911ff12798a8a18d237e9739f58a6b04e4988899fe", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "ea6e87f774c8608d60c8d34022a7d073bd7680a0a013f049fc62bf35efea1044"},
|
"plug_cowboy": {:hex, :plug_cowboy, "2.5.2", "62894ccd601cf9597e2c23911ff12798a8a18d237e9739f58a6b04e4988899fe", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "ea6e87f774c8608d60c8d34022a7d073bd7680a0a013f049fc62bf35efea1044"},
|
||||||
"plug_crypto": {:hex, :plug_crypto, "1.2.3", "8f77d13aeb32bfd9e654cb68f0af517b371fb34c56c9f2b58fe3df1235c1251a", [:mix], [], "hexpm", "b5672099c6ad5c202c45f5a403f21a3411247f164e4a8fab056e5cd8a290f4a2"},
|
"plug_crypto": {:hex, :plug_crypto, "1.2.3", "8f77d13aeb32bfd9e654cb68f0af517b371fb34c56c9f2b58fe3df1235c1251a", [:mix], [], "hexpm", "b5672099c6ad5c202c45f5a403f21a3411247f164e4a8fab056e5cd8a290f4a2"},
|
||||||
|
"poison": {:hex, :poison, "5.0.0", "d2b54589ab4157bbb82ec2050757779bfed724463a544b6e20d79855a9e43b24", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "11dc6117c501b80c62a7594f941d043982a1bd05a1184280c0d9166eb4d8d3fc"},
|
||||||
"postgrex": {:hex, :postgrex, "0.16.5", "fcc4035cc90e23933c5d69a9cd686e329469446ef7abba2cf70f08e2c4b69810", [:mix], [{:connection, "~> 1.1", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "edead639dc6e882618c01d8fc891214c481ab9a3788dfe38dd5e37fd1d5fb2e8"},
|
"postgrex": {:hex, :postgrex, "0.16.5", "fcc4035cc90e23933c5d69a9cd686e329469446ef7abba2cf70f08e2c4b69810", [:mix], [{:connection, "~> 1.1", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "edead639dc6e882618c01d8fc891214c481ab9a3788dfe38dd5e37fd1d5fb2e8"},
|
||||||
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
|
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
|
||||||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
|
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
|
||||||
|
|||||||
@ -3,7 +3,7 @@ defmodule Friends.Repo.Migrations.AddAddressesToFriends do
|
|||||||
|
|
||||||
def change do
|
def change do
|
||||||
alter table(:friends) do
|
alter table(:friends) do
|
||||||
add :address, :string
|
add :address_id, references(:places)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Loading…
Reference in New Issue
Block a user