diff --git a/friends/assets/js/app.js b/friends/assets/js/app.js
index b99021a..9457ec5 100644
--- a/friends/assets/js/app.js
+++ b/friends/assets/js/app.js
@@ -21,8 +21,8 @@
// Include phoenix_html to handle method=PUT/DELETE in forms and buttons.
import "phoenix_html"
// Establish Phoenix Socket and LiveView configuration.
-import {Socket} from "phoenix"
-import {LiveSocket} from "phoenix_live_view"
+import { Socket } from "phoenix"
+import { LiveSocket } from "phoenix_live_view"
import topbar from "../vendor/topbar"
import mapboxgl from "../vendor/mapbox-gl"
@@ -30,12 +30,12 @@ let Hooks = {};
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {
- hooks: Hooks,
- params: { _csrf_token: csrfToken }
+ hooks: Hooks,
+ params: { _csrf_token: csrfToken }
})
// Show progress bar on live navigation and form submits
-topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"})
+topbar.config({ barColors: { 0: "#29d" }, shadowColor: "rgba(0, 0, 0, .3)" })
window.addEventListener("phx:page-loading-start", info => topbar.show())
window.addEventListener("phx:page-loading-stop", info => topbar.hide())
@@ -49,35 +49,58 @@ liveSocket.connect()
window.liveSocket = liveSocket
window.hideElement = function (id) {
- var el = document.getElementById(id);
- el.hidden = true;
+ var el = document.getElementById(id);
+ el.hidden = true;
}
-window.selectResult = function (latlon, display) {
- var name_el = document.querySelector("[autocomplete=name]");
- var latlon_el = document.querySelector("[autocomplete=latlon]");
+window.selectMapResult = function (latlon, display) {
+ var name_el = document.querySelector("[autocomplete=name]");
+ var latlon_el = document.querySelector("[autocomplete=latlon]");
- name_el.value = display;
- latlon_el.value = latlon;
+ name_el.value = display;
+ latlon_el.value = latlon;
- window.liveSocket.hooks.showMapbox.initMap();
+ window.liveSocket.hooks.showMapbox.initMap();
};
+window.selectRelation = function (id, name) {
+ var e = new Event('eventSender');
+ e.data = {
+ id: id,
+ name: name
+ }
+ window.dispatchEvent(e);
+}
+
+Hooks.NewRelation = {
+ mounted() {
+ var list_el = document.querySelector("div#relationships");
+ window.addEventListener("eventSender", e => {
+ this.pushEvent("select_relation", e.data, function (reply) {
+ console.log(reply);
+ })
+ })
+
+ }
+}
+
Hooks.showMapbox = {
- initMap() {
- mapboxgl.accessToken = 'pk.eyJ1IjoicnlhbnBhbmR5YSIsImEiOiJja3psM2tlcDA1MXl1Mm9uZmo5bGxpNzdxIn0.TwBKpTTypcD5fWFc8XRyHg';
-
- const latlon = JSON.parse(document.querySelector("[autocomplete=latlon]").value).reverse();
-
- const map = new mapboxgl.Map({
- container: 'map',
- style: 'mapbox://styles/mapbox/outdoors-v11',
- center: latlon,
- zoom: 8
- });
- },
-
- mounted() {
- this.initMap();
- }
+ initMap() {
+ mapboxgl.accessToken = 'pk.eyJ1IjoicnlhbnBhbmR5YSIsImEiOiJja3psM2tlcDA1MXl1Mm9uZmo5bGxpNzdxIn0.TwBKpTTypcD5fWFc8XRyHg';
+
+ const latlon = JSON.parse(document.querySelector("[autocomplete=latlon]").value).reverse();
+
+ const map = new mapboxgl.Map({
+ container: 'map',
+ style: 'mapbox://styles/mapbox/outdoors-v11',
+ center: latlon,
+ zoom: 8
+ });
+ },
+
+ mounted() {
+ if (this.el.getAttribute("latlon") != "null") {
+ this.initMap();
+ }
+ }
}
\ No newline at end of file
diff --git a/friends/lib/friends/friend.ex b/friends/lib/friends/friend.ex
index da7ae34..a238e9b 100644
--- a/friends/lib/friends/friend.ex
+++ b/friends/lib/friends/friend.ex
@@ -23,14 +23,16 @@ defmodule Friends.Friend do
:relationships,
Friends.Friend,
join_through: Relationship,
- join_keys: [friend_id: :id, relation_id: :id]
+ join_keys: [friend_id: :id, relation_id: :id],
+ on_delete: :delete_all
)
many_to_many(
:reverse_relationships,
Friends.Friend,
join_through: Relationship,
- join_keys: [relation_id: :id, friend_id: :id]
+ join_keys: [relation_id: :id, friend_id: :id],
+ on_delete: :delete_all
)
end
@@ -46,10 +48,10 @@ defmodule Friends.Friend do
:user_id,
:address_id
])
- |> Ecto.Changeset.validate_required([:name, :email, :phone, :born],
+ |> Ecto.Changeset.validate_required([:name],
message: "This field is required."
)
- |> Ecto.Changeset.validate_format(:name, ~r/\w+\ \w+/, message: "Please enter your full name.")
+ # |> Ecto.Changeset.validate_format(:name, ~r/\w+\ \w+/, message: "Please enter your full name.")
|> Ecto.Changeset.validate_format(
:email,
Regex.compile!("^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$"),
@@ -88,7 +90,7 @@ defmodule Friends.Friend do
end
def new(params \\ %{}) do
- %Friend{id: :new}
+ %Friend{id: nil}
|> struct(params)
end
@@ -120,13 +122,13 @@ defmodule Friends.Friend do
end
def create(params \\ %{id: nil}) do
- %Friend{}
- |> Friend.changeset(%{params | id: nil})
+ Friend.new()
+ |> Friend.changeset(params)
|> Map.put(:action, :insert)
end
def update(params) do
- Friend.get_by_id(params.id |> String.to_integer())
+ Friend.get_by_id(params.id)
|> Friend.changeset(params)
|> Map.put(:action, :update)
end
@@ -156,12 +158,12 @@ defmodule Friends.Friend do
def create_or_update(params) do
case params.id do
- "new" ->
+ nil ->
params
|> create()
|> generate_slug()
- |> create_birth_event()
|> commit()
+ |> create_birth_event()
_number ->
params
@@ -189,7 +191,8 @@ defmodule Friends.Friend do
end
def can_be_edited_by(friend, user) do
- if user |> is_nil(), do: false, else: friend.id == user.profile.id
+ true
+ # if user |> is_nil(), do: false, else: friend.id == user.profile.id
end
def assign_address(%Friend{} = friend, address) do
@@ -211,8 +214,10 @@ defmodule Friends.Friend do
end
def assign_user!(%Friend{} = friend) do
- %{friend: new_friend, user: _user} = assign_user(friend)
- new_friend
+ case assign_user(friend) do
+ %{friend: new_friend, user: _user} -> new_friend
+ nil -> friend
+ end
end
def load_user(%Friends.Friend{user: %Ecto.Association.NotLoaded{}} = model) do
@@ -260,7 +265,7 @@ defmodule Friends.Friend do
end
def create_birth_event(%Friend{id: id} = friend) do
- solo_relationship = Relationship.get_or_new(friend, friend)
+ solo_relationship = Relationship.get_or_create(friend, friend)
Event.get_or_create(%{
name: "Born",
@@ -270,4 +275,14 @@ defmodule Friends.Friend do
relationship_id: solo_relationship.id
})
end
+
+ def create_relationship(friend1, friend2) do
+ rel = Relationship.get_or_create(friend1, friend2)
+ rel |> Relationship.members()
+ end
+
+ def delete_relationship(friend1, friend2) do
+ Relationship.delete(friend1, friend2)
+ friend1.id |> Friend.get_by_id()
+ end
end
diff --git a/friends/lib/friends/friend/search.ex b/friends/lib/friends/friend/search.ex
new file mode 100644
index 0000000..44e20b2
--- /dev/null
+++ b/friends/lib/friends/friend/search.ex
@@ -0,0 +1,44 @@
+defmodule Friends.Friend.Search do
+ alias Friends.Friend
+ import Ecto.Query
+
+ @repo Friends.Repo
+
+ def autocomplete(str, friend) do
+ @repo.all(
+ from(
+ f in Friend,
+ where: ilike(f.name, ^"%#{str}%")
+ )
+ )
+ |> remove_self(friend)
+ |> remove_existing(friend)
+ end
+
+ defp remove_self(list, friend) do
+ list
+ |> Enum.filter(fn result ->
+ result.id != friend.id
+ end)
+ end
+
+ defp remove_existing(list, friend) do
+ existing =
+ friend
+ |> Helpers.relations()
+ |> Enum.map(& &1.id)
+
+ list
+ |> Enum.filter(fn result ->
+ result.id not in existing
+ end)
+ end
+
+ def parse_result(friend) do
+ %{
+ id: "friend-#{friend.id}",
+ value: friend.id,
+ name: friend.name
+ }
+ end
+end
diff --git a/friends/lib/friends/places/search.ex b/friends/lib/friends/places/search.ex
index a7b173f..9874182 100644
--- a/friends/lib/friends/places/search.ex
+++ b/friends/lib/friends/places/search.ex
@@ -1,4 +1,7 @@
defmodule Friends.Places.Search do
+ import Ecto.Query
+ @repo Friends.Repo
+
def api_key,
do:
"pk.eyJ1IjoicnlhbnBhbmR5YSIsImEiOiJja3psM2tlcDA1MXl1Mm9uZmo5bGxpNzdxIn0.TwBKpTTypcD5fWFc8XRyHg"
@@ -14,6 +17,22 @@ defmodule Friends.Places.Search do
]
end
+ def known_places(str) do
+ @repo.all(
+ from(
+ p in Friends.Places.Place,
+ where: ilike(p.name, ^"%#{str}%")
+ )
+ )
+ |> Enum.map(
+ &%{
+ "center" => &1.latlon,
+ "place_name" => &1.name,
+ "id" => "known.#{&1.id}"
+ }
+ )
+ end
+
def autocomplete(str, region \\ nil) do
viewbox =
if region do
@@ -25,8 +44,9 @@ defmodule Friends.Places.Search do
response = HTTPoison.get!(url)
results = Poison.decode!(response.body)
+ IO.inspect(results["features"])
- results["features"]
+ known_places(str) ++ results["features"]
end
def parse_features(%{
@@ -36,7 +56,7 @@ defmodule Friends.Places.Search do
}) do
%{
name: name,
- latlon: lonlat |> Enum.reverse() |> Poison.encode!(),
+ value: lonlat |> Enum.reverse() |> Poison.encode!(),
id: id |> String.replace(".", "-")
}
end
diff --git a/friends/lib/friends/relationship.ex b/friends/lib/friends/relationship.ex
index 20ca34b..1eee859 100644
--- a/friends/lib/friends/relationship.ex
+++ b/friends/lib/friends/relationship.ex
@@ -82,7 +82,7 @@ defmodule Friends.Relationship do
rel_type = if id1 == id2, do: 0, else: type
relationship =
- @repo.insert(%Relationship{
+ @repo.insert!(%Relationship{
friend_id: id1,
relation_id: id2,
type: rel_type
@@ -122,6 +122,10 @@ defmodule Friends.Relationship do
end
end
+ def delete(a, b) do
+ get(a, b) |> Friends.Repo.delete!()
+ end
+
def get_by_slugs([slug1, slug2]) do
friend1 = slug1 |> Friend.get_by_slug()
friend2 = slug2 |> Friend.get_by_slug()
diff --git a/friends/lib/friends_web/live/components/autocomplete.ex b/friends/lib/friends_web/live/components/autocomplete.ex
index 0e10102..d1e639e 100644
--- a/friends/lib/friends_web/live/components/autocomplete.ex
+++ b/friends/lib/friends_web/live/components/autocomplete.ex
@@ -4,19 +4,29 @@ defmodule FriendsWeb.Components.Autocomplete do
alias Phoenix.LiveView.JS
+ def bolden(string, substring) do
+ String.replace(
+ string,
+ substring,
+ "#{substring}"
+ )
+ |> Phoenix.HTML.raw()
+ end
+
def search_results(assigns) do
~H"""
-
+
<%= if @search_results do %>
-
+
<%= for r <- @search_results do %>
- -
+
-
<.link id={r[:id]}
- latlon={r[:latlon]}
+ phx_value={r[:value]}
class="search_result"
- onMouseDown={"selectResult('#{r[:latlon]}', '#{r[:name]}')"}>
- <%= r[:name] %>
+ phx-hook="NewRelation"
+ onMouseDown={"#{@select_fxn}('#{r[:value]}', '#{r[:name]}')"}>
+ <%= r[:name] |> bolden(@search_query) %>
<% end %>
@@ -24,29 +34,6 @@ defmodule FriendsWeb.Components.Autocomplete do
<% end %>
-
-
"""
end
end
diff --git a/friends/lib/friends_web/live/components/cards.ex b/friends/lib/friends_web/live/components/cards.ex
new file mode 100644
index 0000000..865b891
--- /dev/null
+++ b/friends/lib/friends_web/live/components/cards.ex
@@ -0,0 +1,25 @@
+defmodule FriendsWeb.Components.Cards do
+ use FriendsWeb, :live_component
+
+ def relationship_card(assigns) do
+ ~H"""
+
+

+
+
+ <.link navigate={Routes.friends_show_path(FriendsWeb.Endpoint, :overview, @relation.slug)} class=""><%=@relation.name%>
+ <%= if @relationship |> Friends.Relationship.get_relation do %>
+
Friends.Relationship.get_color}"}><%= @relationship |> Friends.Relationship.get_relation %>
+ <% end %>
+
+
If a dog chews shoes whose shoes does he choose?
+
+
+ <%= if @editable do %>
+ Delete
+ <% end %>
+
+
+ """
+ end
+end
diff --git a/friends/lib/friends_web/live/components/components.ex b/friends/lib/friends_web/live/components/components.ex
index 4a49a90..8aba494 100644
--- a/friends/lib/friends_web/live/components/components.ex
+++ b/friends/lib/friends_web/live/components/components.ex
@@ -4,7 +4,7 @@ defmodule FriendsWeb.FriendsLive.Components do
import Helpers
import FriendsWeb.LiveHelpers
alias Friends.Friend
- alias FriendsWeb.Components.{Autocomplete, Map}
+ alias FriendsWeb.Components.{Autocomplete, Map, Cards}
alias Phoenix.LiveView.JS
def header(assigns) do
@@ -48,7 +48,9 @@ defmodule FriendsWeb.FriendsLive.Components do
def show_page(:overview, assigns) do
~H"""
-
+ <%= if @address_latlon != "null" do %>
+
+ <% end %>
-
Nickname:
@@ -77,8 +79,12 @@ defmodule FriendsWeb.FriendsLive.Components do
-
Address:
+ <%= if @address_latlon == "null" do %>
+ none
+ <% else %>
<%= @address %>
-
+ <% end %>
+
"""
@@ -105,22 +111,11 @@ defmodule FriendsWeb.FriendsLive.Components do
def show_page(:relationships, assigns) do
~H"""
- <%= for relation <- @friend |> relations do %>
- <% relationship = relation(@friend, relation) %>
-
-

-
-
- <%= relation.name %>
- <%= if relationship |> Friends.Relationship.get_relation do %>
-
Friends.Relationship.get_color}"}><%= relationship |> Friends.Relationship.get_relation %>
- <% end %>
-
-
If a dog chews shoes whose shoes does he choose?
-
-
+ <%= for relation <- @relationships do %>
+ <% relationship = relation(@friend, relation) %>
+
<% end %>
- <%= if @friend |> relations |> Enum.empty? do %>
+ <%= if @relationships |> Enum.empty? do %>
No relationships on record yet.
<% end %>
@@ -160,14 +155,12 @@ defmodule FriendsWeb.FriendsLive.Components do
<%= error_tag f, :name %>
- <%= if @address_latlon do %>
-
- <% end %>
+
-
Email:
- <%= text_input f, :email, class: "input input-primary input-sm md:input-md input-disabled", phx_debounce: "blur", value: @current_user.email %>
+ <%= text_input f, :email, class: "input input-primary input-sm md:input-md input-disabled", phx_debounce: "blur", value: @friend.email %>
<%= error_tag f, :email %>
@@ -194,7 +187,7 @@ defmodule FriendsWeb.FriendsLive.Components do
-
Address:
- <%= text_input f, :address_query, value: @address_query,
+ <%= text_input f, :search_query, value: @search_query,
class: "input input-primary input-sm md:input-md",
phx_debounce: "500",
phx_change: :address_search,
@@ -206,7 +199,11 @@ defmodule FriendsWeb.FriendsLive.Components do
phx_change: "validate"
%>
-
+
@@ -234,6 +231,41 @@ defmodule FriendsWeb.FriendsLive.Components do
def edit_page(:relationships, assigns) do
~H"""
+ <%= show_page(:relationships, assigns) %>
+
+ <.form for={@changeset} let={f}>
+
+ -
+ Type a name:
+
+ <%= text_input f, :search_query, value: @search_query,
+ class: "input input-primary input-sm md:input-md",
+ phx_debounce: "500",
+ phx_change: :relation_search,
+ phx_click: JS.show(to: "#search-results"),
+ phx_blur: JS.hide(to: "#search-results"),
+ autocomplete: "name" %>
+ <%= hidden_input f, :relation_id, value: @relation_id,
+ id: "relation-id", autocomplete: "relation-id",
+ phx_change: "validate"
+ %>
+
+
+
+
+
+
"""
end
diff --git a/friends/lib/friends_web/live/edit.ex b/friends/lib/friends_web/live/edit.ex
index 25ebe2b..e962678 100644
--- a/friends/lib/friends_web/live/edit.ex
+++ b/friends/lib/friends_web/live/edit.ex
@@ -28,6 +28,7 @@ defmodule FriendsWeb.FriendsLive.Edit do
live_action = socket.assigns.live_action || :overview
friend = Friend.get_by_slug(slug)
+ editable = friend |> Friend.can_be_edited_by(socket.assigns[:current_user])
if(live_action) do
{:ok,
@@ -35,18 +36,24 @@ defmodule FriendsWeb.FriendsLive.Edit do
|> assign(:live_action, live_action)
|> assign_current_user(token |> Map.get("user_token"))
|> assign(:friend, friend)
+ |> assign(:editable, editable)
|> assign(:action, Routes.friends_path(socket, :update))
|> title(friend.name <> " - " <> (live_action |> titlecase))
|> assign(:changeset, %Friend{} |> Friend.changeset())
- |> assign(:address_query, nil)
+ |> assign(:search_query, nil)
|> assign(:search_results, nil)}
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
+ # Overview form page
+ def handle_params(
+ %{"slug" => slug} = _attrs,
+ _url,
+ %{assigns: %{live_action: :overview}} = socket
+ ) do
+ live_action = socket.assigns.live_action
friend = Friend.get_by_slug(slug)
editable = friend |> Friend.can_be_edited_by(socket.assigns[:current_user])
@@ -58,13 +65,57 @@ defmodule FriendsWeb.FriendsLive.Edit do
|> assign_friend(friend)
|> assign(:action, Routes.friends_path(socket, :update))
|> assign(:live_action, live_action)
- |> assign(:address_query, address_query)
+ |> assign(:search_query, address_query)
|> assign(:address_latlon, address_latlon |> Poison.encode!())
|> assign(:search_results, nil)
|> title(friend.name <> " - " <> (live_action |> titlecase))
|> assign(:editable, editable)}
end
+ # Add a relationship
+ def handle_params(
+ %{"slug" => slug} = _attrs,
+ _url,
+ %{assigns: %{live_action: :relationships}} = socket
+ ) do
+ live_action = socket.assigns.live_action
+
+ friend = Friend.get_by_slug(slug)
+ editable = friend |> Friend.can_be_edited_by(socket.assigns[:current_user])
+
+ {:noreply,
+ socket
+ |> assign_friend(friend)
+ |> assign(:relationships, friend |> relations)
+ |> assign(:live_action, live_action)
+ |> assign(:search_query, nil)
+ |> assign(:relation_id, nil)
+ |> assign(:search_results, nil)
+ |> assign(:editable, editable)
+ |> title(friend.name <> " - " <> (live_action |> titlecase))}
+ end
+
+ # Timeline edit
+ def handle_params(
+ %{"slug" => slug} = _attrs,
+ _url,
+ %{assigns: %{live_action: :timeline}} = socket
+ ) do
+ live_action = socket.assigns.live_action
+
+ friend = Friend.get_by_slug(slug)
+
+ {:noreply,
+ socket
+ |> assign_friend(friend)
+ |> assign(:live_action, live_action)
+ |> assign(:search_query, nil)
+ |> assign(:relation_id, nil)
+ |> assign(:search_results, nil)
+ |> title(friend.name <> " - " <> (live_action |> titlecase))}
+ end
+
+ # Catch-all (aka, new friend form)
def handle_params(_attrs, _token, socket) do
friend = Friend.new()
@@ -77,7 +128,12 @@ defmodule FriendsWeb.FriendsLive.Edit do
|> title("Welcome")}
end
- def handle_event("validate", %{"friend" => form_params}, %{assigns: %{friend: friend}} = socket) do
+ # Validate overview form page
+ def handle_event(
+ "validate",
+ %{"friend" => form_params},
+ %{assigns: %{friend: friend, live_action: :overview}} = socket
+ ) do
id = form_params["id"] |> parse_id
name = form_params["name"]
nickname = form_params["nickname"]
@@ -126,7 +182,7 @@ defmodule FriendsWeb.FriendsLive.Edit do
slug = form_params["slug"] || name |> to_slug
id = form_params["id"] || :new
address_latlon = form_params["address_latlon"] |> Poison.decode!()
- address_query = form_params["address_query"]
+ address_query = form_params["search_query"]
address = %Friends.Places.Place{
name: address_query,
@@ -134,8 +190,14 @@ defmodule FriendsWeb.FriendsLive.Edit do
}
new_address =
- address
- |> Friends.Places.Place.get_or_create()
+ case address.latlon do
+ nil ->
+ %{id: nil}
+
+ _ ->
+ address
+ |> Friends.Places.Place.get_or_create()
+ end
new_params = %{
id: id,
@@ -161,17 +223,61 @@ defmodule FriendsWeb.FriendsLive.Edit do
}
end
- def handle_event("address_search", %{"friend" => %{"address_query" => query}}, socket) do
+ def handle_event("address_search", %{"friend" => %{"search_query" => query}}, socket) do
results = Places.Search.autocomplete(query) |> Enum.map(&Places.Search.parse_features/1)
if query == "" do
{:noreply, socket |> assign(:search_results, nil)}
else
- {:noreply, socket |> assign(:search_results, results)}
+ {:noreply,
+ socket
+ |> assign(:search_results, results)
+ |> assign(:search_query, query)
+ |> assign(:select_fxn, "selectMapResult")}
end
end
- def handle_event(event, unsigned_params, socket) do
+ def handle_event(
+ "relation_search",
+ %{"friend" => %{"search_query" => query}},
+ %{assigns: %{friend: friend}} = socket
+ ) do
+ if query == "" do
+ {:noreply, socket |> assign(:search_results, nil)}
+ else
+ results =
+ (Friend.Search.autocomplete(query, friend) ++
+ [Friend.new(%{name: query})])
+ |> Enum.map(&Friend.Search.parse_result/1)
+
+ {:noreply,
+ socket
+ |> assign(:search_results, results)
+ |> assign(:search_query, query)
+ |> assign(:select_fxn, "selectRelation")}
+ end
+ end
+
+ def handle_event(
+ "select_relation",
+ %{"id" => rel_id, "name" => rel_name},
+ %{assigns: %{friend: friend, relationships: relationships}} = socket
+ ) do
+ new_rel =
+ case rel_id do
+ "new" -> Friend.create(%{name: rel_name})
+ _num -> Friend.get_by_id(rel_id |> String.to_integer())
+ end
+
+ [updated_friend, updated_relation] = friend |> Friend.create_relationship(new_rel)
+
+ {:noreply,
+ socket
+ |> assign_friend(updated_friend)
+ |> assign(:relationships, updated_friend |> relations)}
+ end
+
+ def handle_event(_event, _unsigned_params, socket) do
{:noreply, socket}
end
end
diff --git a/friends/lib/friends_web/live/show.ex b/friends/lib/friends_web/live/show.ex
index dfa5377..ee17540 100644
--- a/friends/lib/friends_web/live/show.ex
+++ b/friends/lib/friends_web/live/show.ex
@@ -19,7 +19,7 @@ defmodule FriendsWeb.FriendsLive.Show do
|> assign_current_user(token |> Map.get("user_token"))
|> assign(:friend, friend)
|> assign(:address, address)
- |> assign(:latlon, latlon |> Poison.encode!())
+ |> assign(:address_latlon, latlon |> Poison.encode!())
|> title(friend.name <> " - " <> (live_action |> titlecase))
|> assign(:changeset, %Friend{} |> Friend.changeset())
|> assign(:editable, editable)
@@ -29,16 +29,35 @@ defmodule FriendsWeb.FriendsLive.Show do
end
end
- def handle_params(%{"slug" => slug} = attrs, _url, socket) do
- live_action = socket.assigns.live_action || false
-
+ def handle_params(
+ %{"slug" => slug} = attrs,
+ _url,
+ %{assigns: %{friend: friend, live_action: :overview}} = socket
+ ) do
friend = Friend.get_by_slug(slug)
editable = friend |> Friend.can_be_edited_by(socket.assigns[:current_user])
+ live_action = socket.assigns.live_action
{:noreply,
socket
|> assign_friend(friend)
- |> assign(:live_action, live_action)
+ |> title(friend.name <> " - " <> (live_action |> titlecase))
+ |> assign(:editable, editable)}
+ end
+
+ def handle_params(
+ %{"slug" => slug} = attrs,
+ _url,
+ %{assigns: %{friend: friend, live_action: :relationships}} = socket
+ ) do
+ friend = Friend.get_by_slug(slug)
+ editable = friend |> Friend.can_be_edited_by(socket.assigns[:current_user])
+ live_action = socket.assigns.live_action
+
+ {:noreply,
+ socket
+ |> assign_friend(friend)
+ |> assign(:relationships, friend |> Helpers.relations())
|> title(friend.name <> " - " <> (live_action |> titlecase))
|> assign(:editable, editable)}
end
diff --git a/friends/lib/friends_web/views/live_helpers.ex b/friends/lib/friends_web/views/live_helpers.ex
index 731db1c..ff7e795 100644
--- a/friends/lib/friends_web/views/live_helpers.ex
+++ b/friends/lib/friends_web/views/live_helpers.ex
@@ -84,7 +84,6 @@ defmodule FriendsWeb.LiveHelpers do
socket
|> assign(:friend, friend)
|> assign(:changeset, friend |> Friend.changeset())
- |> assign(:relationships, friend.relationships)
end
# Same thing, but this time we have a changeset we want to keep
@@ -92,6 +91,5 @@ defmodule FriendsWeb.LiveHelpers do
socket
|> assign(:friend, friend)
|> assign(:changeset, changeset)
- |> assign(:relationships, friend.relationships)
end
end
diff --git a/friends/lib/helpers/helpers.ex b/friends/lib/helpers/helpers.ex
index 457fb00..0d9fd39 100644
--- a/friends/lib/helpers/helpers.ex
+++ b/friends/lib/helpers/helpers.ex
@@ -90,4 +90,32 @@ defmodule Helpers do
def events(%Friends.Relationship{} = relationship) do
relationship.events
end
+
+ def random_string(length) do
+ :crypto.strong_rand_bytes(length)
+ |> Base.url_encode64()
+ |> binary_part(0, length)
+ |> String.replace(~r/-/, "")
+ end
+
+ def unique_friend_email, do: "user#{System.unique_integer()}@example.com"
+ def valid_friend_name, do: "#{random_string(5)} Mc#{random_string(5)}"
+ def valid_friend_phone, do: "+1 (917) 624 2939" |> Helpers.format_phone()
+ def valid_friend_birthdate, do: ~D"1990-05-05"
+
+ def valid_friend_attributes(attrs \\ %{}) do
+ Enum.into(attrs, %{
+ id: nil,
+ name: valid_friend_name(),
+ phone: valid_friend_phone(),
+ born: valid_friend_birthdate(),
+ email: unique_friend_email()
+ })
+ end
+
+ def friend_fixture(attrs \\ %{}) do
+ attrs
+ |> valid_friend_attributes()
+ |> Friends.Friend.create_or_update()
+ end
end