From 686bb489ba95ff3ae6a9531fc5d95cd0a7a07d19 Mon Sep 17 00:00:00 2001 From: Adam Piontek Date: Wed, 24 Mar 2021 19:35:49 -0400 Subject: [PATCH] initial work on allowing import from ics/iCal --- assets/js/app.js | 1 + .../live/shift_import_live/index.ex | 63 +++++++++++++++++++ .../live/shift_import_live/index.html.leex | 35 +++++++++++ lib/shift73k_web/router.ex | 2 + .../layout/navbar/_shifts_menu.html.eex | 6 ++ mix.exs | 3 +- mix.lock | 1 + 7 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 lib/shift73k_web/live/shift_import_live/index.ex create mode 100644 lib/shift73k_web/live/shift_import_live/index.html.leex diff --git a/assets/js/app.js b/assets/js/app.js index 5f83b83e..b9f19848 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -56,6 +56,7 @@ import "../node_modules/bootstrap-icons/icons/save.svg"; import "../node_modules/bootstrap-icons/icons/asterisk.svg"; import "../node_modules/bootstrap-icons/icons/card-list.svg"; import "../node_modules/bootstrap-icons/icons/file-earmark-spreadsheet.svg"; +import "../node_modules/bootstrap-icons/icons/box-arrow-in-left.svg"; // webpack automatically bundles all modules in your // entry points. Those entry points can be configured diff --git a/lib/shift73k_web/live/shift_import_live/index.ex b/lib/shift73k_web/live/shift_import_live/index.ex new file mode 100644 index 00000000..9da8abb9 --- /dev/null +++ b/lib/shift73k_web/live/shift_import_live/index.ex @@ -0,0 +1,63 @@ +defmodule Shift73kWeb.ShiftImportLive.Index do + use Shift73kWeb, :live_view + + @impl true + def mount(_params, session, socket) do + HTTPoison.start() + + socket + |> assign_defaults(session) + |> live_okreply() + end + + @impl true + def handle_event("save", %{"ics_import" => %{"ics_url" => ics_url}}, socket) do + ics_url + |> IO.inspect(label: "given ical url :") + |> HTTPoison.get!() + |> handle_http_ics_response(socket) + end + + defp handle_http_ics_response(%HTTPoison.Response{status_code: 200} = resp, socket) do + case content_type_calendar?(resp.headers) do + false -> + handle_http_ics_response(false, socket) + + true -> + resp.body + |> ICalendar.from_ics() + |> handle_parsed_ics_data(socket) + end + end + + defp handle_http_ics_response(_, socket) do + socket + |> put_flash(:error, "Bad data, bad URL, or some other error") + |> live_noreply() + end + + defp handle_parsed_ics_data([], socket), do: handle_http_ics_response(false, socket) + + defp handle_parsed_ics_data(events, socket) do + IO.inspect(events, label: "We got some ical events! :") + + socket + |> put_flash(:success, "We got some ical events") + |> live_noreply() + end + + def ical_request(ics_url) do + # ics_url = "https://calendar.google.com/calendar/ical/l44mcggj2rsoqq7prlakvitqfo%40group.calendar.google.com/private-66f4cf8b340bdd6e9de8c60b2ae36528/basic.ics" + end + + defp content_type_calendar?(headers) do + headers + |> List.keyfind("Content-Type", 0) + |> elem(1) + |> String.contains?("text/calendar") + end + + def shift_from_event(%ICalendar.Event{} = event) do + %{} + end +end diff --git a/lib/shift73k_web/live/shift_import_live/index.html.leex b/lib/shift73k_web/live/shift_import_live/index.html.leex new file mode 100644 index 00000000..3edf3548 --- /dev/null +++ b/lib/shift73k_web/live/shift_import_live/index.html.leex @@ -0,0 +1,35 @@ +
+
+ +

+ <%= icon_div @socket, "bi-box-arrow-in-left", [class: "icon baseline"] %> + Import Shifts +

+ +

If you have an iCal/ics formatted calendar hosted elsewhere, provide its URL here to import its events.

+ +
+
+ + <%= form_for :ics_import, "#", [phx_submit: "save"], fn iimf -> %> + +
+
+ <%= label iimf, :ics_url, "iCal/ics URL", class: "form-label" %> + <%= url_input iimf, :ics_url, class: "form-control" %> +
+
+ +
+
+ <%= submit "Submit", class: "btn btn-primary" %> +
+
+ + <% end %> + +
+
+ +
+
diff --git a/lib/shift73k_web/router.ex b/lib/shift73k_web/router.ex index a22c1a95..1cdf67b0 100644 --- a/lib/shift73k_web/router.ex +++ b/lib/shift73k_web/router.ex @@ -106,6 +106,8 @@ defmodule Shift73kWeb.Router do get "/csv", UserShiftsCsvController, :new post "/csv", UserShiftsCsvController, :export + + live "/import", ShiftImportLive.Index, :index end # scope "/", Shift73kWeb do diff --git a/lib/shift73k_web/templates/layout/navbar/_shifts_menu.html.eex b/lib/shift73k_web/templates/layout/navbar/_shifts_menu.html.eex index 137f8140..ae472ab1 100644 --- a/lib/shift73k_web/templates/layout/navbar/_shifts_menu.html.eex +++ b/lib/shift73k_web/templates/layout/navbar/_shifts_menu.html.eex @@ -34,6 +34,12 @@ CSV Export <% end %> +
  • + <%= link nav_link_opts(@conn, to: Routes.shift_import_index_path(@conn, :index), class: "dropdown-item") do %> + <%= icon_div @conn, "bi-box-arrow-in-left", [class: "icon baseline me-1"] %> + iCal Import + <% end %> +
  • diff --git a/mix.exs b/mix.exs index 9d064ea5..520ec53b 100644 --- a/mix.exs +++ b/mix.exs @@ -53,7 +53,8 @@ defmodule Shift73k.MixProject do {:scrivener_ecto, "~> 2.0"}, {:tzdata, "~> 1.1"}, {:nimble_csv, "~> 1.0"}, - {:icalendar, "~> 1.1"} + {:icalendar, "~> 1.1"}, + {:httpoison, "~> 1.7"} ] end diff --git a/mix.lock b/mix.lock index 578aa5fe..7149b0ff 100644 --- a/mix.lock +++ b/mix.lock @@ -21,6 +21,7 @@ "gettext": {:hex, :gettext, "0.18.2", "7df3ea191bb56c0309c00a783334b288d08a879f53a7014341284635850a6e55", [:mix], [], "hexpm", "f9f537b13d4fdd30f3039d33cb80144c3aa1f8d9698e47d7bcbcc8df93b1f5c5"}, "hackney": {:hex, :hackney, "1.17.4", "99da4674592504d3fb0cfef0db84c3ba02b4508bae2dff8c0108baa0d6e0977c", [:rebar3], [{:certifi, "~>2.6.1", [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", "de16ff4996556c8548d512f4dbe22dd58a587bf3332e7fd362430a7ef3986b16"}, "html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"}, + "httpoison": {:hex, :httpoison, "1.8.0", "6b85dea15820b7804ef607ff78406ab449dd78bed923a49c7160e1886e987a3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "28089eaa98cf90c66265b6b5ad87c59a3729bea2e74e9d08f9b51eb9729b3c3a"}, "hut": {:hex, :hut, "1.3.0", "71f2f054e657c03f959cf1acc43f436ea87580696528ca2a55c8afb1b06c85e7", [:"erlang.mk", :rebar, :rebar3], [], "hexpm", "7e15d28555d8a1f2b5a3a931ec120af0753e4853a4c66053db354f35bf9ab563"}, "icalendar": {:hex, :icalendar, "1.1.0", "898a8640abb32d161d990e419999004718a7a4b48be31f48db248f90ca33fa6e", [:mix], [{:timex, "~> 3.4", [hex: :timex, repo: "hexpm", optional: false]}], "hexpm", "a131f45fbabd2ee5a22e6bc49ea91e81131158394e7169274cee866263640dca"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},