2021-03-24 19:35:49 -04:00
|
|
|
defmodule Shift73kWeb.ShiftImportLive.Index do
|
|
|
|
use Shift73kWeb, :live_view
|
|
|
|
|
2021-03-25 15:28:39 -04:00
|
|
|
alias Shift73k.Repo
|
|
|
|
alias Shift73k.Shifts
|
|
|
|
|
|
|
|
@url_regex_str "[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)"
|
|
|
|
@url_regex Regex.compile!(@url_regex_str)
|
|
|
|
|
2021-03-24 19:35:49 -04:00
|
|
|
@impl true
|
|
|
|
def mount(_params, session, socket) do
|
|
|
|
HTTPoison.start()
|
|
|
|
|
|
|
|
socket
|
|
|
|
|> assign_defaults(session)
|
2021-03-25 20:31:32 -04:00
|
|
|
|> assign(:page_title, "iCal Import")
|
2021-03-25 18:09:53 -04:00
|
|
|
|> assign(:url_valid, false)
|
|
|
|
|> assign(:url_validated, false)
|
|
|
|
|> assign(:tz_valid, true)
|
2021-03-24 19:35:49 -04:00
|
|
|
|> live_okreply()
|
|
|
|
end
|
|
|
|
|
|
|
|
@impl true
|
2021-03-25 15:28:39 -04:00
|
|
|
def handle_event("validate", %{"ics_import" => %{"ics_url" => url, "time_zone" => tz}}, socket) do
|
|
|
|
socket
|
2021-03-25 18:09:53 -04:00
|
|
|
|> assign(:url_valid, Regex.match?(@url_regex, url))
|
2021-03-25 15:28:39 -04:00
|
|
|
|> assign(:url_validated, true)
|
|
|
|
|> assign(:tz_valid, Enum.member?(Tzdata.zone_list(), tz))
|
|
|
|
|> live_noreply()
|
|
|
|
end
|
|
|
|
|
|
|
|
@impl true
|
|
|
|
def handle_event("save", %{"ics_import" => %{"ics_url" => url, "time_zone" => tz}}, socket) do
|
|
|
|
url
|
2021-03-24 19:35:49 -04:00
|
|
|
|> HTTPoison.get!()
|
2021-03-25 15:28:39 -04:00
|
|
|
|> handle_http_ics_response(socket, tz)
|
2021-03-24 19:35:49 -04:00
|
|
|
end
|
|
|
|
|
2021-03-25 15:28:39 -04:00
|
|
|
defp handle_http_ics_response(%HTTPoison.Response{status_code: 200} = resp, socket, tz) do
|
2021-03-24 19:35:49 -04:00
|
|
|
case content_type_calendar?(resp.headers) do
|
|
|
|
false ->
|
2021-03-25 15:28:39 -04:00
|
|
|
handle_http_ics_response(false, socket, tz)
|
2021-03-24 19:35:49 -04:00
|
|
|
|
|
|
|
true ->
|
|
|
|
resp.body
|
|
|
|
|> ICalendar.from_ics()
|
2021-03-25 15:28:39 -04:00
|
|
|
|> handle_parsed_ics_data(socket, tz)
|
2021-03-24 19:35:49 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-03-25 15:28:39 -04:00
|
|
|
defp handle_http_ics_response(_, socket, _tz) do
|
2021-03-24 19:35:49 -04:00
|
|
|
socket
|
2021-03-25 15:28:39 -04:00
|
|
|
|> put_flash(:error, "Bad data, bad URL, or some other error. Page the dev!")
|
2021-03-24 19:35:49 -04:00
|
|
|
|> live_noreply()
|
|
|
|
end
|
|
|
|
|
2021-03-25 15:28:39 -04:00
|
|
|
defp handle_parsed_ics_data([], socket, tz), do: handle_http_ics_response(false, socket, tz)
|
2021-03-24 19:35:49 -04:00
|
|
|
|
2021-03-25 15:28:39 -04:00
|
|
|
defp handle_parsed_ics_data(events, socket, tz) do
|
2021-03-25 18:09:53 -04:00
|
|
|
events
|
|
|
|
|> Stream.map(&shift_from_event(&1, tz, socket.assigns.current_user.id))
|
|
|
|
|> Enum.map(&Repo.timestamp/1)
|
|
|
|
|> Shifts.create_multiple()
|
|
|
|
|> handle_create_multiple_result(length(events), socket)
|
|
|
|
|> live_noreply()
|
2021-03-24 19:35:49 -04:00
|
|
|
end
|
|
|
|
|
2021-03-25 15:28:39 -04:00
|
|
|
defp handle_create_multiple_result(result, event_count, socket) do
|
|
|
|
{status, msg} =
|
|
|
|
case result do
|
|
|
|
{:error, errmsg} ->
|
|
|
|
{:error, "Ope, problem error inserting shifts, page the dev! Message: #{errmsg}"}
|
|
|
|
|
|
|
|
{n, _} ->
|
|
|
|
s = (n > 1 && "s") || ""
|
|
|
|
|
|
|
|
if n == event_count do
|
|
|
|
{:success, "Successfully imported #{n} event#{s}"}
|
|
|
|
else
|
2021-03-25 18:09:53 -04:00
|
|
|
{:warning,
|
|
|
|
"Some error, only #{n} event#{s} imported but seemed like iCal contained #{
|
|
|
|
event_count
|
|
|
|
}?"}
|
2021-03-25 15:28:39 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
put_flash(socket, status, msg)
|
2021-03-24 19:35:49 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
defp content_type_calendar?(headers) do
|
|
|
|
headers
|
|
|
|
|> List.keyfind("Content-Type", 0)
|
|
|
|
|> elem(1)
|
|
|
|
|> String.contains?("text/calendar")
|
|
|
|
end
|
|
|
|
|
2021-03-25 15:28:39 -04:00
|
|
|
defp shift_from_event(%ICalendar.Event{} = e, tz, user_id) do
|
|
|
|
dtzstart = DateTime.shift_zone!(e.dtstart, tz)
|
|
|
|
dtzend = DateTime.add(dtzstart, DateTime.diff(e.dtend, e.dtstart))
|
|
|
|
|
|
|
|
%{
|
|
|
|
subject: e.summary,
|
|
|
|
location: e.location,
|
|
|
|
description: fix_description(e.description),
|
|
|
|
date: DateTime.to_date(dtzstart),
|
|
|
|
time_zone: tz,
|
|
|
|
time_start: DateTime.to_time(dtzstart),
|
|
|
|
time_end: DateTime.to_time(dtzend),
|
|
|
|
user_id: user_id
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2021-03-25 20:01:39 -04:00
|
|
|
defp fix_description(nil), do: nil
|
|
|
|
|
2021-03-25 15:28:39 -04:00
|
|
|
defp fix_description(description) do
|
|
|
|
description
|
|
|
|
|> String.replace("<br>", "\r\n")
|
|
|
|
|> String.replace("<br\\>", "\r\n")
|
|
|
|
|> String.replace("<br \\>", "\r\n")
|
|
|
|
|> String.replace("<b>", "**")
|
|
|
|
|> String.replace("</b>", "**")
|
|
|
|
|> String.replace("<strong>", "**")
|
|
|
|
|> String.replace("</strong>", "**")
|
|
|
|
|> String.replace("<i>", "*")
|
|
|
|
|> String.replace("</i>", "*")
|
|
|
|
|> String.replace("<em>", "*")
|
|
|
|
|> String.replace("</em>", "*")
|
2021-03-24 19:35:49 -04:00
|
|
|
end
|
|
|
|
end
|