From 8957f2d1dd85daffe2588db628108468a651a724 Mon Sep 17 00:00:00 2001 From: Adam Piontek Date: Fri, 19 Mar 2021 16:38:52 -0400 Subject: [PATCH] much progress on shift assigning & app navigation --- lib/shift73k/shifts.ex | 32 ++++-- lib/shift73k/shifts/templates.ex | 6 +- .../shifts/templates/shift_template.ex | 5 +- .../controllers/other_controller.ex | 16 --- lib/shift73k_web/live/modal_component.ex | 11 +- lib/shift73k_web/live/page_live.ex | 40 ------- lib/shift73k_web/live/page_live.html.leex | 49 -------- .../shift_assign_live/delete_component.ex | 42 +++++++ .../delete_component.html.leex | 31 +++++ .../live/shift_assign_live/index.ex | 108 ++++++++++++++---- .../live/shift_assign_live/index.html.leex | 29 +++-- .../shift_template_live/delete_component.ex | 5 - .../delete_component.html.leex | 2 +- .../shift_template_live/form_component.ex | 5 - .../form_component.html.leex | 2 +- .../live/shift_template_live/index.ex | 31 ++++- .../live/shift_template_live/index.html.leex | 3 +- .../live/user_management/delete_component.ex | 9 +- .../delete_component.html.leex | 2 +- .../live/user_management/form_component.ex | 5 - .../user_management/form_component.html.leex | 2 +- .../live/user_management/index.ex | 44 ++++--- .../live/user_management/index.html.leex | 4 +- lib/shift73k_web/plugs/redirector.ex | 36 ++++++ lib/shift73k_web/router.ex | 3 +- .../templates/layout/_navbar.html.eex | 28 +++-- .../layout/navbar/_shifts_menu.html.eex | 25 ++++ .../layout/navbar/_user_menu.html.eex | 4 - .../templates/other/index.html.eex | 41 ------- lib/shift73k_web/views/other_view.ex | 3 - .../20210306171754_create_shift_templates.exs | 2 +- ...06173113_add_user_default_shift_column.exs | 2 +- test/shift73k_web/live/page_live_test.exs | 66 ----------- 33 files changed, 363 insertions(+), 330 deletions(-) delete mode 100644 lib/shift73k_web/controllers/other_controller.ex delete mode 100644 lib/shift73k_web/live/page_live.ex delete mode 100644 lib/shift73k_web/live/page_live.html.leex create mode 100644 lib/shift73k_web/live/shift_assign_live/delete_component.ex create mode 100644 lib/shift73k_web/live/shift_assign_live/delete_component.html.leex create mode 100644 lib/shift73k_web/plugs/redirector.ex create mode 100644 lib/shift73k_web/templates/layout/navbar/_shifts_menu.html.eex delete mode 100644 lib/shift73k_web/templates/other/index.html.eex delete mode 100644 lib/shift73k_web/views/other_view.ex delete mode 100644 test/shift73k_web/live/page_live_test.exs diff --git a/lib/shift73k/shifts.ex b/lib/shift73k/shifts.ex index 93078c87..8f2aefaa 100644 --- a/lib/shift73k/shifts.ex +++ b/lib/shift73k/shifts.ex @@ -22,13 +22,26 @@ defmodule Shift73k.Shifts do end def list_shifts_by_user_between_dates(user_id, start_date, end_date) do - q = from( - s in Shift, - select: %{date: s.date, subject: s.subject, time_start: s.time_start, time_end: s.time_end}, - where: s.user_id == ^user_id and s.date >= ^start_date and s.date < ^end_date, - order_by: [s.date, s.time_start] - ) - Repo.all(q) + from(s in Shift) + |> select([s], %{ + date: s.date, + subject: s.subject, + time_start: s.time_start, + time_end: s.time_end + }) + |> where([s], s.user_id == ^user_id and s.date >= ^start_date and s.date <= ^end_date) + |> order_by([s], [s.date, s.time_start]) + |> Repo.all() + end + + defp query_shifts_by_user_on_list_of_dates(user_id, date_list) do + from(s in Shift) + |> where([s], s.user_id == ^user_id and s.date in ^date_list) + end + + def list_shifts_by_user_on_list_of_dates(user_id, date_list) do + query_shifts_by_user_on_list_of_dates(user_id, date_list) + |> Repo.all() end @doc """ @@ -99,6 +112,11 @@ defmodule Shift73k.Shifts do Repo.delete(shift) end + def delete_shifts_by_user_on_list_of_dates(user_id, date_list) do + query_shifts_by_user_on_list_of_dates(user_id, date_list) + |> Repo.delete_all() + end + @doc """ Returns an `%Ecto.Changeset{}` for tracking shift changes. diff --git a/lib/shift73k/shifts/templates.ex b/lib/shift73k/shifts/templates.ex index 286f555d..6530802f 100644 --- a/lib/shift73k/shifts/templates.ex +++ b/lib/shift73k/shifts/templates.ex @@ -22,7 +22,11 @@ defmodule Shift73k.Shifts.Templates do end def list_shift_templates_by_user_id(user_id) do - q = from s in ShiftTemplate, where: s.user_id == ^user_id, order_by: [s.subject, s.time_start] + q = + from s in ShiftTemplate, + where: s.user_id == ^user_id, + order_by: [fragment("lower(?)", s.subject), s.time_start] + Repo.all(q) end diff --git a/lib/shift73k/shifts/templates/shift_template.ex b/lib/shift73k/shifts/templates/shift_template.ex index 55ad1a56..ee749f65 100644 --- a/lib/shift73k/shifts/templates/shift_template.ex +++ b/lib/shift73k/shifts/templates/shift_template.ex @@ -19,6 +19,7 @@ defmodule Shift73k.Shifts.Templates.ShiftTemplate do field :time_end, :time, default: ~T[17:00:00] belongs_to(:user, Shift73k.Accounts.User) + has_one(:is_fave_of_user, Shift73k.Accounts.User, foreign_key: :fave_shift_template_id) timestamps() end @@ -58,7 +59,9 @@ defmodule Shift73k.Shifts.Templates.ShiftTemplate do [] end end) - |> validate_inclusion(:time_zone, Timex.timezones(), message: "must be a valid IANA tz database time zone") + |> validate_inclusion(:time_zone, Timex.timezones(), + message: "must be a valid IANA tz database time zone" + ) end defp time_start_from_attrs(%{"time_start" => time_start}), do: time_start diff --git a/lib/shift73k_web/controllers/other_controller.ex b/lib/shift73k_web/controllers/other_controller.ex deleted file mode 100644 index 942377cf..00000000 --- a/lib/shift73k_web/controllers/other_controller.ex +++ /dev/null @@ -1,16 +0,0 @@ -defmodule Shift73kWeb.OtherController do - use Shift73kWeb, :controller - - def index(conn, _params) do - conn - |> put_flash(:success, "Log in was a success. Good for you.") - |> put_flash(:error, "Lorem ipsum dolor sit amet consectetur adipisicing elit.") - |> put_flash( - :info, - "Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatibus dolore sunt quia aperiam sint id reprehenderit? Dolore incidunt alias inventore accusantium nulla optio, ducimus eius aliquam hic, pariatur voluptate distinctio." - ) - |> put_flash(:warning, "Oh no, there's nothing to worry about!") - |> put_flash(:primary, "Something in the brand color.") - |> render("index.html") - end -end diff --git a/lib/shift73k_web/live/modal_component.ex b/lib/shift73k_web/live/modal_component.ex index 3fc7d984..b3f165e3 100644 --- a/lib/shift73k_web/live/modal_component.ex +++ b/lib/shift73k_web/live/modal_component.ex @@ -16,10 +16,10 @@ defmodule Shift73kWeb.ModalComponent do - <%= live_component @socket, @component, @opts %> + <%= live_component @socket, @component, Keyword.put(@opts, :modal_id, @id) %> @@ -27,6 +27,11 @@ defmodule Shift73kWeb.ModalComponent do """ end + @impl true + def update(assigns, socket) do + socket |> assign(assigns) |> live_okreply() + end + @impl true def handle_event("close", _, socket) do send(self(), {:close_modal, true}) @@ -35,6 +40,6 @@ defmodule Shift73kWeb.ModalComponent do @impl true def handle_event("hide", _, socket) do - {:noreply, push_event(socket, "modal-please-hide", %{})} + socket |> push_event("modal-please-hide", %{}) |> live_noreply() end end diff --git a/lib/shift73k_web/live/page_live.ex b/lib/shift73k_web/live/page_live.ex deleted file mode 100644 index aba5f081..00000000 --- a/lib/shift73k_web/live/page_live.ex +++ /dev/null @@ -1,40 +0,0 @@ -defmodule Shift73kWeb.PageLive do - use Shift73kWeb, :live_view - - @impl true - def mount(_params, session, socket) do - socket = assign_defaults(socket, session) - {:ok, assign(socket, query: "", results: %{})} - end - - @impl true - def handle_event("suggest", %{"q" => query}, socket) do - {:noreply, assign(socket, results: search(query), query: query)} - end - - @impl true - def handle_event("search", %{"q" => query}, socket) do - case search(query) do - %{^query => vsn} -> - {:noreply, redirect(socket, external: "https://hexdocs.pm/#{query}/#{vsn}")} - - _ -> - {:noreply, - socket - |> put_flash(:error, "No dependencies found matching \"#{query}\"") - |> assign(results: %{}, query: query)} - end - end - - defp search(query) do - if not Shift73kWeb.Endpoint.config(:code_reloader) do - raise "action disabled when not in development" - end - - for {app, desc, vsn} <- Application.started_applications(), - app = to_string(app), - String.starts_with?(app, query) and not List.starts_with?(desc, ~c"ERTS"), - into: %{}, - do: {app, vsn} - end -end diff --git a/lib/shift73k_web/live/page_live.html.leex b/lib/shift73k_web/live/page_live.html.leex deleted file mode 100644 index daf2334a..00000000 --- a/lib/shift73k_web/live/page_live.html.leex +++ /dev/null @@ -1,49 +0,0 @@ -
-

<%= gettext "Welcome to %{name}!", name: "Phoenix" %>

-

Peace of mind from prototype to production

- -
- - - <%= for {app, _vsn} <- @results do %> - - <% end %> - - -
-
- -
- - - -
diff --git a/lib/shift73k_web/live/shift_assign_live/delete_component.ex b/lib/shift73k_web/live/shift_assign_live/delete_component.ex new file mode 100644 index 00000000..8dc279cb --- /dev/null +++ b/lib/shift73k_web/live/shift_assign_live/delete_component.ex @@ -0,0 +1,42 @@ +defmodule Shift73kWeb.ShiftAssignLive.DeleteComponent do + use Shift73kWeb, :live_component + + alias Shift73k.Shifts + + @impl true + def update(assigns, socket) do + socket + |> assign(assigns) + |> assign_dates() + |> live_okreply() + end + + defp assign_dates(%{assigns: %{delete_days_shifts: daylist}} = socket) do + date_list = Enum.map(daylist, &Date.from_iso8601!/1) + year_map = Enum.group_by(date_list, fn d -> d.year end) + assign(socket, date_list: date_list, date_map: build_date_map(year_map)) + end + + def build_date_map(year_map) do + year_map + |> Map.keys() + |> Enum.reduce(year_map, fn y, acc -> + Map.put(acc, y, Enum.group_by(acc[y], fn d -> d.month end)) + end) + end + + @impl true + def handle_event("confirm-delete-days-shifts", _params, socket) do + user = socket.assigns.current_user + date_list = socket.assigns.date_list + {n, _} = Shifts.delete_shifts_by_user_on_list_of_dates(user.id, date_list) + s = (n > 1 && "s") || "" + flash = {:info, "Successfully deleted #{n} assigned shift#{s}"} + send(self(), {:put_flash_message, flash}) + send(self(), {:clear_selected_days, true}) + + socket + |> push_event("modal-please-hide", %{}) + |> live_noreply() + end +end diff --git a/lib/shift73k_web/live/shift_assign_live/delete_component.html.leex b/lib/shift73k_web/live/shift_assign_live/delete_component.html.leex new file mode 100644 index 00000000..f159bcdf --- /dev/null +++ b/lib/shift73k_web/live/shift_assign_live/delete_component.html.leex @@ -0,0 +1,31 @@ + + diff --git a/lib/shift73k_web/live/shift_assign_live/index.ex b/lib/shift73k_web/live/shift_assign_live/index.ex index 60535bbd..91640d52 100644 --- a/lib/shift73k_web/live/shift_assign_live/index.ex +++ b/lib/shift73k_web/live/shift_assign_live/index.ex @@ -18,9 +18,10 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do socket |> assign_defaults(session) |> assign(:custom_shift, @custom_shift) - |> assign(:show_template_btn_active, :false) - |> assign(:show_template_details, :false) + |> assign(:show_template_btn_active, false) + |> assign(:show_template_details, false) |> assign(:selected_days, []) + |> assign(:delete_days_shifts, nil) |> live_okreply() end @@ -32,12 +33,18 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do |> show_details_if_custom() |> assign_shift_length() |> assign_shift_template_changeset() + |> assign_modal_close_handlers() |> init_today(Timex.today()) |> init_calendar() |> assign_known_shifts() |> live_noreply() end + defp assign_modal_close_handlers(socket) do + to = Routes.shift_assign_index_path(socket, :index) + assign(socket, modal_return_to: to, modal_close_action: :return) + end + defp get_shift_template("custom-shift"), do: @custom_shift defp get_shift_template(template_id), do: Templates.get_shift_template(template_id) @@ -56,11 +63,11 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do defp init_calendar(%{assigns: %{current_user: user}} = socket) do days = day_names(user.week_start_at) {first, last, rows} = week_rows(socket.assigns.cursor_date, user.week_start_at) - assign(socket, [day_names: days, week_rows: rows, day_first: first, day_last: last]) + assign(socket, day_names: days, week_rows: rows, day_first: first, day_last: last) end defp init_today(socket, today) do - assign(socket, [current_date: today, cursor_date: today]) + assign(socket, current_date: today, cursor_date: today) end defp assign_shift_template_changeset(%{assigns: %{shift_template: shift}} = socket) do @@ -71,7 +78,7 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do defp init_shift_template(socket) do first_list_id = socket.assigns.shift_templates |> hd() |> elem(1) fave_id = socket.assigns.current_user.fave_shift_template_id - assign_shift_template(socket, (fave_id || first_list_id)) + assign_shift_template(socket, fave_id || first_list_id) end defp assign_shift_template(socket, template_id) do @@ -83,14 +90,17 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do Templates.list_shift_templates_by_user_id(user.id) |> Enum.map(fn t -> shift_template_option(t, user.fave_shift_template_id) end) |> Enum.concat([@custom_shift_opt]) + assign(socket, :shift_templates, shift_templates) end defp shift_template_option(template, fave_id) do label = - template.subject <> " (" <> - format_shift_time(template.time_start) <> "—" <> - format_shift_time(template.time_end) <> ")" + template.subject <> + " (" <> + format_shift_time(template.time_start) <> + "—" <> + format_shift_time(template.time_end) <> ")" label = case fave_id == template.id do @@ -126,7 +136,7 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do week_rows = Interval.new(from: first, until: last, right_open: false) - |> Enum.map(& NaiveDateTime.to_date(&1)) + |> Enum.map(&NaiveDateTime.to_date(&1)) |> Enum.chunk_every(7) {first, last, week_rows} @@ -141,11 +151,14 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do true -> "bg-triangle-white" end - Timex.compare(day, current_date, :days) == 0 -> "bg-info text-white" + Timex.compare(day, current_date, :days) == 0 -> + "bg-info text-white" - day.month != cursor_date.month -> "bg-light text-gray" + day.month != cursor_date.month -> + "bg-light text-gray" - true -> "" + true -> + "" end end @@ -157,11 +170,12 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do end defp show_details_if_custom(socket) do - if (socket.assigns.shift_template.id != @custom_shift.id) || socket.assigns.show_template_details do + if socket.assigns.shift_template.id != @custom_shift.id || + socket.assigns.show_template_details do socket else socket - |> assign(:show_template_btn_active, :true) + |> assign(:show_template_btn_active, true) |> push_event("toggle-template-details", %{targetId: "#templateDetailsCol"}) end end @@ -197,7 +211,11 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do end @impl true - def handle_event("change-selected-template", %{"template_select" => %{"template" => template_id}}, socket) do + def handle_event( + "change-selected-template", + %{"template_select" => %{"template" => template_id}}, + socket + ) do socket |> assign_shift_template(template_id) |> show_details_if_custom() @@ -210,9 +228,11 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do def handle_event("month-nav", %{"month" => direction}, socket) do new_cursor = cond do - direction == "now" -> Timex.today() + direction == "now" -> + Timex.today() + true -> - months = direction == "prev" && -1 || 1 + months = (direction == "prev" && -1) || 1 Timex.shift(socket.assigns.cursor_date, months: months) end @@ -229,12 +249,12 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do @impl true def handle_event("collapse-shown", %{"target_id" => _target_id}, socket) do - {:noreply, assign(socket, :show_template_details, :true)} + {:noreply, assign(socket, :show_template_details, true)} end @impl true def handle_event("collapse-hidden", %{"target_id" => _target_id}, socket) do - {:noreply, assign(socket, :show_template_details, :false)} + {:noreply, assign(socket, :show_template_details, false)} end @impl true @@ -248,6 +268,14 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do {:noreply, assign(socket, :selected_days, selected_days)} end + @impl true + def handle_event("delete-days-shifts", _params, socket) do + socket + |> assign(:modal_close_action, :delete_days_shifts) + |> assign(:delete_days_shifts, socket.assigns.selected_days) + |> live_noreply() + end + @impl true def handle_event("clear-days", _params, socket) do {:noreply, assign(socket, :selected_days, [])} @@ -259,7 +287,8 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do shift_data = shift_data_from_template(socket.assigns.shift_template) # 2. create list of shift attrs to insert - to_insert = Enum.map(socket.assigns.selected_days, &shift_from_day_and_shift_data(&1, shift_data)) + to_insert = + Enum.map(socket.assigns.selected_days, &shift_from_day_and_shift_data(&1, shift_data)) # 3. insert the data {status, msg} = insert_shifts(to_insert, length(socket.assigns.selected_days)) @@ -271,10 +300,37 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do |> live_noreply() end + @impl true + def handle_info({:put_flash_message, {flash_type, msg}}, socket) do + socket |> put_flash(flash_type, msg) |> live_noreply() + end + + @impl true + def handle_info({:clear_selected_days, _}, socket) do + socket |> assign(:selected_days, []) |> live_noreply() + end + + @impl true + def handle_info({:close_modal, _}, %{assigns: %{modal_close_action: :return}} = socket) do + socket + |> copy_flash() + |> push_patch(to: socket.assigns.modal_return_to) + |> live_noreply() + end + + @impl true + def handle_info({:close_modal, _}, %{assigns: %{modal_close_action: assign_key}} = socket) do + socket + |> assign(assign_key, nil) + |> assign_modal_close_handlers() + |> assign_known_shifts() + |> live_noreply() + end + defp shift_data_from_template(shift_template) do shift_template |> Map.from_struct() - |> Map.drop([:__meta__, :id, :inserted_at, :updated_at, :user]) + |> Map.drop([:__meta__, :id, :inserted_at, :updated_at, :user, :is_fave_of_user]) end defp shift_from_day_and_shift_data(day, shift_data) do @@ -289,12 +345,16 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do |> Repo.transaction() |> case do {:ok, %{insert_all: {n, _}}} -> + s = (n > 1 && "s") || "" + if n == day_count do - {:success, "Successfully assigned shift to #{n} day(s)"} + {:success, "Successfully assigned shift to #{n} day#{s}"} else - {:warning, "Some error, only #{n} day(s) inserted but #{day_count} were selected"} + {:warning, "Some error, only #{n} day#{s} inserted but #{day_count} were selected"} end - _ -> {:error, "Ope, unknown error inserting shifts, page the dev"} + + _ -> + {:error, "Ope, unknown error inserting shifts, page the dev"} end end diff --git a/lib/shift73k_web/live/shift_assign_live/index.html.leex b/lib/shift73k_web/live/shift_assign_live/index.html.leex index c5136885..a8160bfa 100644 --- a/lib/shift73k_web/live/shift_assign_live/index.html.leex +++ b/lib/shift73k_web/live/shift_assign_live/index.html.leex @@ -1,3 +1,13 @@ +<%= if @delete_days_shifts do %> + <%= live_modal @socket, Shift73kWeb.ShiftAssignLive.DeleteComponent, + id: "delete-days-shifts-#{@current_user.id}", + title: "Delete Shifts From Selected Days", + delete_days_shifts: @delete_days_shifts, + current_user: @current_user + %> +<% end %> + +

<%= icon_div @socket, "bi-calendar2-plus", [class: "icon baseline"] %> Assign Shift To Dates @@ -223,17 +233,22 @@ -
-
+
+
- - + +
diff --git a/lib/shift73k_web/live/shift_template_live/delete_component.ex b/lib/shift73k_web/live/shift_template_live/delete_component.ex index 71205ab3..44209db5 100644 --- a/lib/shift73k_web/live/shift_template_live/delete_component.ex +++ b/lib/shift73k_web/live/shift_template_live/delete_component.ex @@ -11,11 +11,6 @@ defmodule Shift73kWeb.ShiftTemplateLive.DeleteComponent do |> live_okreply() end - @impl true - def handle_event("cancel", _, socket) do - {:noreply, push_event(socket, "modal-please-hide", %{})} - end - @impl true def handle_event("confirm", %{"id" => id, "subject" => subject}, socket) do id diff --git a/lib/shift73k_web/live/shift_template_live/delete_component.html.leex b/lib/shift73k_web/live/shift_template_live/delete_component.html.leex index a14f6a74..8c121a75 100644 --- a/lib/shift73k_web/live/shift_template_live/delete_component.html.leex +++ b/lib/shift73k_web/live/shift_template_live/delete_component.html.leex @@ -8,7 +8,7 @@