From e911217a834156cdf5c61cb5088acfa5dfed61de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Veikko=20Lintuj=C3=A4rvi?= Date: Wed, 7 Jun 2023 18:21:33 +0300 Subject: [PATCH] Autogen calendars --- lib/osuuspuutarha/season.ex | 104 +++++++++++++++++ lib/osuuspuutarha/season/calendar.ex | 19 ++++ .../live/calendar_live/form_component.ex | 55 +++++++++ .../calendar_live/form_component.html.heex | 24 ++++ .../live/calendar_live/index.ex | 46 ++++++++ .../live/calendar_live/index.html.heex | 41 +++++++ .../live/calendar_live/show.ex | 21 ++++ .../live/calendar_live/show.html.heex | 31 ++++++ lib/osuuspuutarha_web/router.ex | 7 ++ .../20230607151852_create_calendars.exs | 15 +++ test/osuuspuutarha/season_test.exs | 61 ++++++++++ .../live/calendar_live_test.exs | 105 ++++++++++++++++++ test/support/fixtures/season_fixtures.ex | 21 ++++ 13 files changed, 550 insertions(+) create mode 100644 lib/osuuspuutarha/season.ex create mode 100644 lib/osuuspuutarha/season/calendar.ex create mode 100644 lib/osuuspuutarha_web/live/calendar_live/form_component.ex create mode 100644 lib/osuuspuutarha_web/live/calendar_live/form_component.html.heex create mode 100644 lib/osuuspuutarha_web/live/calendar_live/index.ex create mode 100644 lib/osuuspuutarha_web/live/calendar_live/index.html.heex create mode 100644 lib/osuuspuutarha_web/live/calendar_live/show.ex create mode 100644 lib/osuuspuutarha_web/live/calendar_live/show.html.heex create mode 100644 priv/repo/migrations/20230607151852_create_calendars.exs create mode 100644 test/osuuspuutarha/season_test.exs create mode 100644 test/osuuspuutarha_web/live/calendar_live_test.exs create mode 100644 test/support/fixtures/season_fixtures.ex diff --git a/lib/osuuspuutarha/season.ex b/lib/osuuspuutarha/season.ex new file mode 100644 index 0000000..14c58f0 --- /dev/null +++ b/lib/osuuspuutarha/season.ex @@ -0,0 +1,104 @@ +defmodule Osuuspuutarha.Season do + @moduledoc """ + The Season context. + """ + + import Ecto.Query, warn: false + alias Osuuspuutarha.Repo + + alias Osuuspuutarha.Season.Calendar + + @doc """ + Returns the list of calendars. + + ## Examples + + iex> list_calendars() + [%Calendar{}, ...] + + """ + def list_calendars do + Repo.all(Calendar) + end + + @doc """ + Gets a single calendar. + + Raises `Ecto.NoResultsError` if the Calendar does not exist. + + ## Examples + + iex> get_calendar!(123) + %Calendar{} + + iex> get_calendar!(456) + ** (Ecto.NoResultsError) + + """ + def get_calendar!(id), do: Repo.get!(Calendar, id) + + @doc """ + Creates a calendar. + + ## Examples + + iex> create_calendar(%{field: value}) + {:ok, %Calendar{}} + + iex> create_calendar(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_calendar(attrs \\ %{}) do + %Calendar{} + |> Calendar.changeset(attrs) + |> Repo.insert() + end + + @doc """ + Updates a calendar. + + ## Examples + + iex> update_calendar(calendar, %{field: new_value}) + {:ok, %Calendar{}} + + iex> update_calendar(calendar, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_calendar(%Calendar{} = calendar, attrs) do + calendar + |> Calendar.changeset(attrs) + |> Repo.update() + end + + @doc """ + Deletes a calendar. + + ## Examples + + iex> delete_calendar(calendar) + {:ok, %Calendar{}} + + iex> delete_calendar(calendar) + {:error, %Ecto.Changeset{}} + + """ + def delete_calendar(%Calendar{} = calendar) do + Repo.delete(calendar) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking calendar changes. + + ## Examples + + iex> change_calendar(calendar) + %Ecto.Changeset{data: %Calendar{}} + + """ + def change_calendar(%Calendar{} = calendar, attrs \\ %{}) do + Calendar.changeset(calendar, attrs) + end +end diff --git a/lib/osuuspuutarha/season/calendar.ex b/lib/osuuspuutarha/season/calendar.ex new file mode 100644 index 0000000..e78a0c0 --- /dev/null +++ b/lib/osuuspuutarha/season/calendar.ex @@ -0,0 +1,19 @@ +defmodule Osuuspuutarha.Season.Calendar do + use Ecto.Schema + import Ecto.Changeset + + schema "calendars" do + field :is_picked_up, :boolean, default: false + field :pickup_date, :date + field :order_id, :id + + timestamps() + end + + @doc false + def changeset(calendar, attrs) do + calendar + |> cast(attrs, [:pickup_date, :is_picked_up]) + |> validate_required([:pickup_date, :is_picked_up]) + end +end diff --git a/lib/osuuspuutarha_web/live/calendar_live/form_component.ex b/lib/osuuspuutarha_web/live/calendar_live/form_component.ex new file mode 100644 index 0000000..7eaf1e3 --- /dev/null +++ b/lib/osuuspuutarha_web/live/calendar_live/form_component.ex @@ -0,0 +1,55 @@ +defmodule OsuuspuutarhaWeb.CalendarLive.FormComponent do + use OsuuspuutarhaWeb, :live_component + + alias Osuuspuutarha.Season + + @impl true + def update(%{calendar: calendar} = assigns, socket) do + changeset = Season.change_calendar(calendar) + + {:ok, + socket + |> assign(assigns) + |> assign(:changeset, changeset)} + end + + @impl true + def handle_event("validate", %{"calendar" => calendar_params}, socket) do + changeset = + socket.assigns.calendar + |> Season.change_calendar(calendar_params) + |> Map.put(:action, :validate) + + {:noreply, assign(socket, :changeset, changeset)} + end + + def handle_event("save", %{"calendar" => calendar_params}, socket) do + save_calendar(socket, socket.assigns.action, calendar_params) + end + + defp save_calendar(socket, :edit, calendar_params) do + case Season.update_calendar(socket.assigns.calendar, calendar_params) do + {:ok, _calendar} -> + {:noreply, + socket + |> put_flash(:info, "Calendar updated successfully") + |> push_redirect(to: socket.assigns.return_to)} + + {:error, %Ecto.Changeset{} = changeset} -> + {:noreply, assign(socket, :changeset, changeset)} + end + end + + defp save_calendar(socket, :new, calendar_params) do + case Season.create_calendar(calendar_params) do + {:ok, _calendar} -> + {:noreply, + socket + |> put_flash(:info, "Calendar created successfully") + |> push_redirect(to: socket.assigns.return_to)} + + {:error, %Ecto.Changeset{} = changeset} -> + {:noreply, assign(socket, changeset: changeset)} + end + end +end diff --git a/lib/osuuspuutarha_web/live/calendar_live/form_component.html.heex b/lib/osuuspuutarha_web/live/calendar_live/form_component.html.heex new file mode 100644 index 0000000..321ad8b --- /dev/null +++ b/lib/osuuspuutarha_web/live/calendar_live/form_component.html.heex @@ -0,0 +1,24 @@ +
+

<%= @title %>

+ + <.form + let={f} + for={@changeset} + id="calendar-form" + phx-target={@myself} + phx-change="validate" + phx-submit="save"> + + <%= label f, :pickup_date %> + <%= date_select f, :pickup_date %> + <%= error_tag f, :pickup_date %> + + <%= label f, :is_picked_up %> + <%= checkbox f, :is_picked_up %> + <%= error_tag f, :is_picked_up %> + +
+ <%= submit "Save", phx_disable_with: "Saving..." %> +
+ +
diff --git a/lib/osuuspuutarha_web/live/calendar_live/index.ex b/lib/osuuspuutarha_web/live/calendar_live/index.ex new file mode 100644 index 0000000..fb630f1 --- /dev/null +++ b/lib/osuuspuutarha_web/live/calendar_live/index.ex @@ -0,0 +1,46 @@ +defmodule OsuuspuutarhaWeb.CalendarLive.Index do + use OsuuspuutarhaWeb, :live_view + + alias Osuuspuutarha.Season + alias Osuuspuutarha.Season.Calendar + + @impl true + def mount(_params, _session, socket) do + {:ok, assign(socket, :calendars, list_calendars())} + end + + @impl true + def handle_params(params, _url, socket) do + {:noreply, apply_action(socket, socket.assigns.live_action, params)} + end + + defp apply_action(socket, :edit, %{"id" => id}) do + socket + |> assign(:page_title, "Edit Calendar") + |> assign(:calendar, Season.get_calendar!(id)) + end + + defp apply_action(socket, :new, _params) do + socket + |> assign(:page_title, "New Calendar") + |> assign(:calendar, %Calendar{}) + end + + defp apply_action(socket, :index, _params) do + socket + |> assign(:page_title, "Listing Calendars") + |> assign(:calendar, nil) + end + + @impl true + def handle_event("delete", %{"id" => id}, socket) do + calendar = Season.get_calendar!(id) + {:ok, _} = Season.delete_calendar(calendar) + + {:noreply, assign(socket, :calendars, list_calendars())} + end + + defp list_calendars do + Season.list_calendars() + end +end diff --git a/lib/osuuspuutarha_web/live/calendar_live/index.html.heex b/lib/osuuspuutarha_web/live/calendar_live/index.html.heex new file mode 100644 index 0000000..1d998fb --- /dev/null +++ b/lib/osuuspuutarha_web/live/calendar_live/index.html.heex @@ -0,0 +1,41 @@ +

Listing Calendars

+ +<%= if @live_action in [:new, :edit] do %> + <.modal return_to={Routes.calendar_index_path(@socket, :index)}> + <.live_component + module={OsuuspuutarhaWeb.CalendarLive.FormComponent} + id={@calendar.id || :new} + title={@page_title} + action={@live_action} + calendar={@calendar} + return_to={Routes.calendar_index_path(@socket, :index)} + /> + +<% end %> + + + + + + + + + + + + <%= for calendar <- @calendars do %> + + + + + + + <% end %> + +
Pickup dateIs picked up
<%= calendar.pickup_date %><%= calendar.is_picked_up %> + <%= live_redirect "Show", to: Routes.calendar_show_path(@socket, :show, calendar) %> + <%= live_patch "Edit", to: Routes.calendar_index_path(@socket, :edit, calendar) %> + <%= link "Delete", to: "#", phx_click: "delete", phx_value_id: calendar.id, data: [confirm: "Are you sure?"] %> +
+ +<%= live_patch "New Calendar", to: Routes.calendar_index_path(@socket, :new) %> diff --git a/lib/osuuspuutarha_web/live/calendar_live/show.ex b/lib/osuuspuutarha_web/live/calendar_live/show.ex new file mode 100644 index 0000000..a422ec2 --- /dev/null +++ b/lib/osuuspuutarha_web/live/calendar_live/show.ex @@ -0,0 +1,21 @@ +defmodule OsuuspuutarhaWeb.CalendarLive.Show do + use OsuuspuutarhaWeb, :live_view + + alias Osuuspuutarha.Season + + @impl true + def mount(_params, _session, socket) do + {:ok, socket} + end + + @impl true + def handle_params(%{"id" => id}, _, socket) do + {:noreply, + socket + |> assign(:page_title, page_title(socket.assigns.live_action)) + |> assign(:calendar, Season.get_calendar!(id))} + end + + defp page_title(:show), do: "Show Calendar" + defp page_title(:edit), do: "Edit Calendar" +end diff --git a/lib/osuuspuutarha_web/live/calendar_live/show.html.heex b/lib/osuuspuutarha_web/live/calendar_live/show.html.heex new file mode 100644 index 0000000..e866d7f --- /dev/null +++ b/lib/osuuspuutarha_web/live/calendar_live/show.html.heex @@ -0,0 +1,31 @@ +

Show Calendar

+ +<%= if @live_action in [:edit] do %> + <.modal return_to={Routes.calendar_show_path(@socket, :show, @calendar)}> + <.live_component + module={OsuuspuutarhaWeb.CalendarLive.FormComponent} + id={@calendar.id} + title={@page_title} + action={@live_action} + calendar={@calendar} + return_to={Routes.calendar_show_path(@socket, :show, @calendar)} + /> + +<% end %> + + + +<%= live_patch "Edit", to: Routes.calendar_show_path(@socket, :edit, @calendar), class: "button" %> | +<%= live_redirect "Back", to: Routes.calendar_index_path(@socket, :index) %> diff --git a/lib/osuuspuutarha_web/router.ex b/lib/osuuspuutarha_web/router.ex index ec1aabc..89474e6 100644 --- a/lib/osuuspuutarha_web/router.ex +++ b/lib/osuuspuutarha_web/router.ex @@ -32,6 +32,13 @@ defmodule OsuuspuutarhaWeb.Router do live "/ilmoittautuminen", OrderLive.Registration, :index live "/ilmoittautuminen/uusi", OrderLive.Registration, :new + + live "/calendars", CalendarLive.Index, :index + live "/calendars/new", CalendarLive.Index, :new + live "/calendars/:id/edit", CalendarLive.Index, :edit + + live "/calendars/:id", CalendarLive.Show, :show + live "/calendars/:id/show/edit", CalendarLive.Show, :edit end scope "/hallinta", OsuuspuutarhaWeb do diff --git a/priv/repo/migrations/20230607151852_create_calendars.exs b/priv/repo/migrations/20230607151852_create_calendars.exs new file mode 100644 index 0000000..2a4a5c0 --- /dev/null +++ b/priv/repo/migrations/20230607151852_create_calendars.exs @@ -0,0 +1,15 @@ +defmodule Osuuspuutarha.Repo.Migrations.CreateCalendars do + use Ecto.Migration + + def change do + create table(:calendars) do + add :pickup_date, :date + add :is_picked_up, :boolean, default: false, null: false + add :order_id, references(:orders, on_delete: :nothing) + + timestamps() + end + + create index(:calendars, [:order_id]) + end +end diff --git a/test/osuuspuutarha/season_test.exs b/test/osuuspuutarha/season_test.exs new file mode 100644 index 0000000..ca921eb --- /dev/null +++ b/test/osuuspuutarha/season_test.exs @@ -0,0 +1,61 @@ +defmodule Osuuspuutarha.SeasonTest do + use Osuuspuutarha.DataCase + + alias Osuuspuutarha.Season + + describe "calendars" do + alias Osuuspuutarha.Season.Calendar + + import Osuuspuutarha.SeasonFixtures + + @invalid_attrs %{is_picked_up: nil, pickup_date: nil} + + test "list_calendars/0 returns all calendars" do + calendar = calendar_fixture() + assert Season.list_calendars() == [calendar] + end + + test "get_calendar!/1 returns the calendar with given id" do + calendar = calendar_fixture() + assert Season.get_calendar!(calendar.id) == calendar + end + + test "create_calendar/1 with valid data creates a calendar" do + valid_attrs = %{is_picked_up: true, pickup_date: ~D[2023-06-06]} + + assert {:ok, %Calendar{} = calendar} = Season.create_calendar(valid_attrs) + assert calendar.is_picked_up == true + assert calendar.pickup_date == ~D[2023-06-06] + end + + test "create_calendar/1 with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = Season.create_calendar(@invalid_attrs) + end + + test "update_calendar/2 with valid data updates the calendar" do + calendar = calendar_fixture() + update_attrs = %{is_picked_up: false, pickup_date: ~D[2023-06-07]} + + assert {:ok, %Calendar{} = calendar} = Season.update_calendar(calendar, update_attrs) + assert calendar.is_picked_up == false + assert calendar.pickup_date == ~D[2023-06-07] + end + + test "update_calendar/2 with invalid data returns error changeset" do + calendar = calendar_fixture() + assert {:error, %Ecto.Changeset{}} = Season.update_calendar(calendar, @invalid_attrs) + assert calendar == Season.get_calendar!(calendar.id) + end + + test "delete_calendar/1 deletes the calendar" do + calendar = calendar_fixture() + assert {:ok, %Calendar{}} = Season.delete_calendar(calendar) + assert_raise Ecto.NoResultsError, fn -> Season.get_calendar!(calendar.id) end + end + + test "change_calendar/1 returns a calendar changeset" do + calendar = calendar_fixture() + assert %Ecto.Changeset{} = Season.change_calendar(calendar) + end + end +end diff --git a/test/osuuspuutarha_web/live/calendar_live_test.exs b/test/osuuspuutarha_web/live/calendar_live_test.exs new file mode 100644 index 0000000..2a14051 --- /dev/null +++ b/test/osuuspuutarha_web/live/calendar_live_test.exs @@ -0,0 +1,105 @@ +defmodule OsuuspuutarhaWeb.CalendarLiveTest do + use OsuuspuutarhaWeb.ConnCase + + import Phoenix.LiveViewTest + import Osuuspuutarha.SeasonFixtures + + @create_attrs %{is_picked_up: true, pickup_date: %{day: 6, month: 6, year: 2023}} + @update_attrs %{is_picked_up: false, pickup_date: %{day: 7, month: 6, year: 2023}} + @invalid_attrs %{is_picked_up: false, pickup_date: %{day: 30, month: 2, year: 2023}} + + defp create_calendar(_) do + calendar = calendar_fixture() + %{calendar: calendar} + end + + describe "Index" do + setup [:create_calendar] + + test "lists all calendars", %{conn: conn} do + {:ok, _index_live, html} = live(conn, Routes.calendar_index_path(conn, :index)) + + assert html =~ "Listing Calendars" + end + + test "saves new calendar", %{conn: conn} do + {:ok, index_live, _html} = live(conn, Routes.calendar_index_path(conn, :index)) + + assert index_live |> element("a", "New Calendar") |> render_click() =~ + "New Calendar" + + assert_patch(index_live, Routes.calendar_index_path(conn, :new)) + + assert index_live + |> form("#calendar-form", calendar: @invalid_attrs) + |> render_change() =~ "is invalid" + + {:ok, _, html} = + index_live + |> form("#calendar-form", calendar: @create_attrs) + |> render_submit() + |> follow_redirect(conn, Routes.calendar_index_path(conn, :index)) + + assert html =~ "Calendar created successfully" + end + + test "updates calendar in listing", %{conn: conn, calendar: calendar} do + {:ok, index_live, _html} = live(conn, Routes.calendar_index_path(conn, :index)) + + assert index_live |> element("#calendar-#{calendar.id} a", "Edit") |> render_click() =~ + "Edit Calendar" + + assert_patch(index_live, Routes.calendar_index_path(conn, :edit, calendar)) + + assert index_live + |> form("#calendar-form", calendar: @invalid_attrs) + |> render_change() =~ "is invalid" + + {:ok, _, html} = + index_live + |> form("#calendar-form", calendar: @update_attrs) + |> render_submit() + |> follow_redirect(conn, Routes.calendar_index_path(conn, :index)) + + assert html =~ "Calendar updated successfully" + end + + test "deletes calendar in listing", %{conn: conn, calendar: calendar} do + {:ok, index_live, _html} = live(conn, Routes.calendar_index_path(conn, :index)) + + assert index_live |> element("#calendar-#{calendar.id} a", "Delete") |> render_click() + refute has_element?(index_live, "#calendar-#{calendar.id}") + end + end + + describe "Show" do + setup [:create_calendar] + + test "displays calendar", %{conn: conn, calendar: calendar} do + {:ok, _show_live, html} = live(conn, Routes.calendar_show_path(conn, :show, calendar)) + + assert html =~ "Show Calendar" + end + + test "updates calendar within modal", %{conn: conn, calendar: calendar} do + {:ok, show_live, _html} = live(conn, Routes.calendar_show_path(conn, :show, calendar)) + + assert show_live |> element("a", "Edit") |> render_click() =~ + "Edit Calendar" + + assert_patch(show_live, Routes.calendar_show_path(conn, :edit, calendar)) + + assert show_live + |> form("#calendar-form", calendar: @invalid_attrs) + |> render_change() =~ "is invalid" + + {:ok, _, html} = + show_live + |> form("#calendar-form", calendar: @update_attrs) + |> render_submit() + |> follow_redirect(conn, Routes.calendar_show_path(conn, :show, calendar)) + + assert html =~ "Calendar updated successfully" + end + end +end diff --git a/test/support/fixtures/season_fixtures.ex b/test/support/fixtures/season_fixtures.ex new file mode 100644 index 0000000..f3199b3 --- /dev/null +++ b/test/support/fixtures/season_fixtures.ex @@ -0,0 +1,21 @@ +defmodule Osuuspuutarha.SeasonFixtures do + @moduledoc """ + This module defines test helpers for creating + entities via the `Osuuspuutarha.Season` context. + """ + + @doc """ + Generate a calendar. + """ + def calendar_fixture(attrs \\ %{}) do + {:ok, calendar} = + attrs + |> Enum.into(%{ + is_picked_up: true, + pickup_date: ~D[2023-06-06] + }) + |> Osuuspuutarha.Season.create_calendar() + + calendar + end +end