Skip to content

Commit

Permalink
use Gcal instead of private functions #31
Browse files Browse the repository at this point in the history
  • Loading branch information
nelsonic committed May 15, 2023
1 parent 44097e7 commit 6b27ea8
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 123 deletions.
3 changes: 3 additions & 0 deletions config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ config :elixir_auth_google,
client_id: "631770888008-6n0oruvsm16kbkqg6u76p5cv5kfkcekt.apps.googleusercontent.com",
client_secret: "MHxv6-RGF5nheXnxh1b0LNDq",
httpoison_mock: true

config :gcal,
httpoison_mock: true
2 changes: 1 addition & 1 deletion lib/cal_web/controllers/google_auth_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ defmodule CalWeb.GoogleAuthController do
def index(conn, %{"code" => code}) do
{:ok, token} = ElixirAuthGoogle.get_token(code, conn)
# {:ok, profile} = ElixirAuthGoogle.get_user_profile(token.access_token)

dbg(token)
conn
# |> put_flash(:person_email, profile.email)
|> put_flash(:token, token)
Expand Down
228 changes: 116 additions & 112 deletions lib/cal_web/live/app_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,18 @@ defmodule CalWeb.AppLive do
def connected_mount(_params, _session, socket) do
# Getting information about the timezone of the client
hoursFromUTC = Map.get(get_connect_params(socket), "hoursFromUTC", "+0000")

dbg(hoursFromUTC)
timezone = Timex.Timezone.name_of(hoursFromUTC)

dbg(timezone)
# We fetch the access token to make the requests.
# If none is found, we redirect the user to the home page.
case get_token(socket) do
{:ok, token} ->
case get_access_token(socket) do
{:ok, access_token} ->

dbg(Timex.now(timezone))
{:ok, primary_calendar} = Gcal.get_calendar_details(access_token, "primary")
# Get event list and update socket
{primary_calendar, event_list} = get_event_list(token, Timex.now(timezone))
{:ok, event_list} = Gcal.get_event_list(access_token, Timex.now(timezone))
{:ok, assign(socket, event_list: event_list.items, calendar: primary_calendar)}

_ ->
Expand All @@ -38,14 +41,14 @@ defmodule CalWeb.AppLive do
socket
) do
# Get token from socket and primary calendar
{:ok, token} = get_token(socket)
{:ok, access_token} = get_access_token(socket)

# Parse new date
datetime =
Timex.parse!("#{year}-#{month}-#{day} #{hoursFromUTC}", "{YYYY}-{M}-{D} {Z}")
|> Timex.to_datetime()

{_primary_calendar, new_event_list} = get_event_list(token, datetime)
{:ok, new_event_list} = Gcal.get_event_list(access_token, datetime)

# Update socket assigns
{:noreply, assign(socket, event_list: new_event_list.items)}
Expand All @@ -67,132 +70,133 @@ defmodule CalWeb.AppLive do
socket
) do
# Get token and primary calendar
{:ok, token} = get_token(socket)

{:ok, access_token} = get_access_token(socket)

event_details = %{
"title" => title,
"date" => date,
"start" => start,
"stop" => stop,
"all_day" => all_day,
"hoursFromUTC" => hoursFromUTC
}
# Post new event
{:ok, _response} =
create_event(token, %{
"title" => title,
"date" => date,
"start" => start,
"stop" => stop,
"all_day" => all_day,
"hoursFromUTC" => hoursFromUTC
})
{:ok, _event} = Gcal.create_event(access_token, event_details)

# Parse new date to datetime and fetch events to refresh
datetime =
Timex.parse!(date, "{YYYY}-{M}-{D}")
|> Timex.to_datetime(Timex.Timezone.name_of(hoursFromUTC))

{_primary_calendar, new_event_list} = get_event_list(token, datetime)
{:ok, new_event_list} = Gcal.get_event_list(access_token, datetime)

{:noreply, assign(socket, event_list: new_event_list.items)}
end

# Gets the event list of primary calendar.
# We pass on the `token` and the `datetime` of the day to fetch the events.
defp get_event_list(token, datetime) do
headers = [Authorization: "Bearer #{token.access_token}", "Content-Type": "application/json"]

# Get primary calendar
{:ok, primary_calendar} =
httpoison().get("https://www.googleapis.com/calendar/v3/calendars/primary", headers)
|> parse_body_response()

# Get events of primary calendar
params = %{
singleEvents: true,
timeMin: datetime |> Timex.beginning_of_day() |> Timex.format!("{RFC3339}"),
timeMax: datetime |> Timex.end_of_day() |> Timex.format!("{RFC3339}")
}

{:ok, event_list} =
httpoison().get(
"https://www.googleapis.com/calendar/v3/calendars/#{primary_calendar.id}/events",
headers,
params: params
)
|> parse_body_response()

{primary_calendar, event_list}
end
# defp get_event_list(token, datetime) do
# headers = [Authorization: "Bearer #{token.access_token}", "Content-Type": "application/json"]
#
# # Get primary calendar
# {:ok, primary_calendar} =
# httpoison().get("https://www.googleapis.com/calendar/v3/calendars/primary", headers)
# |> parse_body_response()
#
# # Get events of primary calendar
# params = %{
# singleEvents: true,
# timeMin: datetime |> Timex.beginning_of_day() |> Timex.format!("{RFC3339}"),
# timeMax: datetime |> Timex.end_of_day() |> Timex.format!("{RFC3339}")
# }
#
# {:ok, event_list} =
# httpoison().get(
# "https://www.googleapis.com/calendar/v3/calendars/#{primary_calendar.id}/events",
# headers,
# params: params
# )
# |> parse_body_response()
#
# {primary_calendar, event_list}
# end

# Create new event to the primary calendar.
defp create_event(token, %{
"title" => title,
"date" => date,
"start" => start,
"stop" => stop,
"all_day" => all_day,
"hoursFromUTC" => hoursFromUTC
}) do
headers = [Authorization: "Bearer #{token.access_token}", "Content-Type": "application/json"]

# Get primary calendar
{:ok, primary_calendar} =
httpoison().get("https://www.googleapis.com/calendar/v3/calendars/primary", headers)
|> parse_body_response()

# Setting `start` and `stop` according to the `all-day` boolean,
# If `all-day` is set to true, we should return the date instead of the datetime,
# as per https://developers.google.com/calendar/api/v3/reference/events/insert.
start =
case all_day do
true ->
%{date: date}

false ->
%{
dateTime:
Timex.parse!("#{date} #{start} #{hoursFromUTC}", "{YYYY}-{0M}-{D} {h24}:{m} {Z}")
|> Timex.format!("{RFC3339}")
}
end

stop =
case all_day do
true ->
%{date: date}

false ->
%{
dateTime:
Timex.parse!("#{date} #{stop} #{hoursFromUTC}", "{YYYY}-{0M}-{D} {h24}:{m} {Z}")
|> Timex.format!("{RFC3339}")
}
end

# Post new event
body = Jason.encode!(%{summary: title, start: start, end: stop})

httpoison().post(
"https://www.googleapis.com/calendar/v3/calendars/#{primary_calendar.id}/events",
body,
headers
)
end
# defp create_event(token, %{
# "title" => title,
# "date" => date,
# "start" => start,
# "stop" => stop,
# "all_day" => all_day,
# "hoursFromUTC" => hoursFromUTC
# }) do
# headers = [Authorization: "Bearer #{token.access_token}", "Content-Type": "application/json"]
#
# # Get primary calendar
# {:ok, primary_calendar} =
# httpoison().get("https://www.googleapis.com/calendar/v3/calendars/primary", headers)
# |> parse_body_response()
#
# # Setting `start` and `stop` according to the `all-day` boolean,
# # If `all-day` is set to true, we should return the date instead of the datetime,
# # as per https://developers.google.com/calendar/api/v3/reference/events/insert.
# start =
# case all_day do
# true ->
# %{date: date}
#
# false ->
# %{
# dateTime:
# Timex.parse!("#{date} #{start} #{hoursFromUTC}", "{YYYY}-{0M}-{D} {h24}:{m} {Z}")
# |> Timex.format!("{RFC3339}")
# }
# end
#
# stop =
# case all_day do
# true ->
# %{date: date}
#
# false ->
# %{
# dateTime:
# Timex.parse!("#{date} #{stop} #{hoursFromUTC}", "{YYYY}-{0M}-{D} {h24}:{m} {Z}")
# |> Timex.format!("{RFC3339}")
# }
# end
#
# # Post new event
# body = Jason.encode!(%{summary: title, start: start, end: stop})
#
# httpoison().post(
# "https://www.googleapis.com/calendar/v3/calendars/#{primary_calendar.id}/events",
# body,
# headers
# )
# end

# Get token from the flash session
defp get_token(socket) do
defp get_access_token(socket) do
case Map.get(socket.assigns.flash, "token") do
nil -> {:error, nil}
token -> {:ok, token}
token ->
{:ok, token.access_token}
end
end

# Parse JSON body response
defp parse_body_response({:ok, response}) do
body = Map.get(response, :body)
# make keys of map atoms for easier access in templates
if body == nil do
{:error, :no_body}
else
{:ok, str_key_map} = Jason.decode(body)
atom_key_map = for {key, val} <- str_key_map, into: %{}, do: {String.to_atom(key), val}
{:ok, atom_key_map}
end

# https://stackoverflow.com/questions/31990134
end
# defp parse_body_response({:ok, response}) do
# body = Map.get(response, :body)
# # make keys of map atoms for easier access in templates
# if body == nil do
# {:error, :no_body}
# else
# {:ok, str_key_map} = Jason.decode(body)
# atom_key_map = for {key, val} <- str_key_map, into: %{}, do: {String.to_atom(key), val}
# {:ok, atom_key_map}
# end
#
# # https://stackoverflow.com/questions/31990134
# end
end
6 changes: 3 additions & 3 deletions lib/cal_web/live/app_live.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<div class="ml-5 pb-2 pr-2 pt-2">
<div class="sm:flex sm:justify-between sm:gap-4">
<h3 class="text-lg font-bold text-gray-900 sm:text-xl">
<span class="mr-3"><%= Map.get(event, "summary") %></span>
<span class="mr-3"><%= Map.get(event, :summary) %></span>
<span class="rounded-full border border-indigo-500 px-3 py-1 text-xs text-indigo-500">
<span class="font-bold"><%= render_start_end_times(event) %></span>
</span>
Expand All @@ -30,8 +30,8 @@
<p class="w-full text-sm text-gray-500">
<span>Organized by: </span>
<span class="font-bold">
<%= Map.get(event, "organizer") |> Map.get("displayName") ||
Map.get(event, "organizer") |> Map.get("email") %>
<%= Map.get(event, :organizer) |> Map.get(:displayName) ||
Map.get(event, :organizer) |> Map.get(:email) %>
</span>
</p>
</div>
Expand Down
12 changes: 6 additions & 6 deletions lib/cal_web/live/app_live_html.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ defmodule CalWeb.AppHTML do
# See https://developers.google.com/calendar/api/v3/reference/events#resource.

{start_type, start_datetime} =
case Map.get(event, "start") |> Map.get("dateTime") do
case Map.get(event, :start) |> Map.get(:dateTime) do
nil ->
{:ok, date} =
Map.get(event, "start") |> Map.get("date") |> Timex.parse("%Y-%m-%d", :strftime)
Map.get(event, :start) |> Map.get(:date) |> Timex.parse("%Y-%m-%d", :strftime)

{:date, date}

Expand All @@ -25,10 +25,10 @@ defmodule CalWeb.AppHTML do
end

{_end_type, end_datetime} =
case Map.get(event, "end") |> Map.get("dateTime") do
case Map.get(event, :end) |> Map.get(:dateTime) do
nil ->
{:ok, date} =
Map.get(event, "start") |> Map.get("date") |> Timex.parse("%Y-%m-%d", :strftime)
Map.get(event, :start) |> Map.get(:date) |> Timex.parse("%Y-%m-%d", :strftime)

{:date, date}

Expand All @@ -53,8 +53,8 @@ defmodule CalWeb.AppHTML do
"""
def render_date(event) do
{:ok, start_datetime} =
case Map.get(event, "start") |> Map.get("dateTime") do
nil -> Map.get(event, "start") |> Map.get("date") |> Timex.parse("%Y-%m-%d", :strftime)
case Map.get(event, :start) |> Map.get(:dateTime) do
nil -> Map.get(event, :start) |> Map.get(:date) |> Timex.parse("%Y-%m-%d", :strftime)
start_datetime -> start_datetime |> Timex.parse("{RFC3339}")
end

Expand Down
2 changes: 2 additions & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ defmodule Cal.MixProject do
# Google auth
{:elixir_auth_google, "~> 1.6.5"},

{:gcal, "~> 1.0.2"},

# HTTPoison
{:httpoison, "~> 2.0"},

Expand Down
2 changes: 2 additions & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"expo": {:hex, :expo, "0.4.1", "1c61d18a5df197dfda38861673d392e642649a9cef7694d2f97a587b2cfb319b", [:mix], [], "hexpm", "2ff7ba7a798c8c543c12550fa0e2cbc81b95d4974c65855d8d15ba7b37a1ce47"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"floki": {:hex, :floki, "0.34.2", "5fad07ef153b3b8ec110b6b155ec3780c4b2c4906297d0b4be1a7162d04a7e02", [:mix], [], "hexpm", "26b9d50f0f01796bc6be611ca815c5e0de034d2128e39cc9702eee6b66a4d1c8"},
"gcal": {:hex, :gcal, "1.0.2", "343e173b0532d8a5a03b85a65e1525a22bec7a49f62a0edb3b0cd252e36f42f1", [:mix], [{:httpoison, "~> 2.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:timex, "~> 3.0", [hex: :timex, repo: "hexpm", optional: false]}, {:useful, "~> 1.11.1", [hex: :useful, repo: "hexpm", optional: false]}], "hexpm", "3ccba5520615768f8ddb92ed0257db10e6de6344bf9145990b01fdf98fea52a8"},
"gettext": {:hex, :gettext, "0.22.1", "e7942988383c3d9eed4bdc22fc63e712b655ae94a672a27e4900e3d4a2c43581", [:mix], [{:expo, "~> 0.4.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "ad105b8dab668ee3f90c0d3d94ba75e9aead27a62495c101d94f2657a190ac5d"},
"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"},
"httpoison": {:hex, :httpoison, "2.0.0", "d38b091f5e481e45cc700aba8121ce49b66d348122a097c9fbc2dc6876d88090", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "f1253bf455be73a4c3f6ae3407e7e3cf6fc91934093e056d737a0566126e2930"},
Expand Down Expand Up @@ -51,6 +52,7 @@
"timex": {:hex, :timex, "3.7.11", "bb95cb4eb1d06e27346325de506bcc6c30f9c6dea40d1ebe390b262fad1862d1", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.20", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.1", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "8b9024f7efbabaf9bd7aa04f65cf8dcd7c9818ca5737677c7b76acbc6a94d1aa"},
"tzdata": {:hex, :tzdata, "1.1.1", "20c8043476dfda8504952d00adac41c6eda23912278add38edc140ae0c5bcc46", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a69cec8352eafcd2e198dea28a34113b60fdc6cb57eb5ad65c10292a6ba89787"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
"useful": {:hex, :useful, "1.11.1", "286cfaa4b543514a9002bf894539a0856b165e84c014f047b199263e1840490a", [:mix], [], "hexpm", "30173ec8e8ad88cb3a5ae2d69c4fc3eec4f8c504415f079545c9dacadea1be9d"},
"websock": {:hex, :websock, "0.5.0", "f6bbce90226121d62a0715bca7c986c5e43de0ccc9475d79c55381d1796368cc", [:mix], [], "hexpm", "b51ac706df8a7a48a2c622ee02d09d68be8c40418698ffa909d73ae207eb5fb8"},
"websock_adapter": {:hex, :websock_adapter, "0.5.0", "cea35d8bbf1a6964e32d4b02ceb561dfb769c04f16d60d743885587e7d2ca55b", [:mix], [{:bandit, "~> 0.6", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "16318b124effab8209b1eb7906c636374f623dc9511a8278ad09c083cea5bb83"},
}
2 changes: 1 addition & 1 deletion test/cal_web/live/app_live_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ defmodule CalWeb.AppLiveTest do

# Should render the page and one event
assert html =~ "List of events"
assert html =~ "Some title"
assert html =~ "First Event"
end

test "no token should redirect to home", %{conn: conn} do
Expand Down

0 comments on commit 6b27ea8

Please sign in to comment.