diff --git a/lib/planner/tasks.ex b/lib/planner/tasks.ex index fab47c3..5501510 100644 --- a/lib/planner/tasks.ex +++ b/lib/planner/tasks.ex @@ -17,6 +17,7 @@ defmodule Planner.Tasks do order_by: [desc: t.updated_at] ) |> Repo.all() + |> Repo.preload(:plans) end def list_unfinished_tasks_by_plan_id(plan_id) do @@ -40,6 +41,7 @@ defmodule Planner.Tasks do order_by: [desc: t.updated_at] ) |> Repo.all() + |> Repo.preload(:plans) end def get_task!(id), do: Repo.get!(Task, id) @@ -60,9 +62,33 @@ defmodule Planner.Tasks do end def update_task(%Task{} = task, attrs) do - task - |> Task.changeset(attrs) - |> Repo.update() + new_plan_details_changesets = Enum.map(attrs["plans"], fn(plan_id) -> + PlanDetail.changeset(%PlanDetail{}, %{"task_id" => task.id, "plan_id" => plan_id}) + end) + + deleted_plan_details = + Ecto.Query.from( + pd in PlanDetail, + where: pd.task_id == ^task.id and pd.plan_id not in ^attrs["plans"] + ) + + multi = + Enum.reduce( + new_plan_details_changesets, + Multi.new() + |> Multi.update(:task, Task.changeset(task, attrs)) + |> Multi.delete_all(:deleted_plan_details, deleted_plan_details), + fn(changeset, new_multi) -> + Multi.insert( + new_multi, + changeset.params["plan_id"], + changeset, + on_conflict: :nothing + ) + end + ) + + Repo.transaction(multi) end def delete_task_by_id!(id) do diff --git a/lib/planner_web/live/tasks_components.ex b/lib/planner_web/live/tasks_components.ex index 66ab8d7..a706932 100644 --- a/lib/planner_web/live/tasks_components.ex +++ b/lib/planner_web/live/tasks_components.ex @@ -50,6 +50,7 @@ defmodule TasksComponent do TaskComponent, id: "task:#{task.id}", task: task, + plans: @plans, live_action: @live_action, is_active: @active_task == task.id, route_show_task: @route_show_task, @@ -96,7 +97,8 @@ defmodule TaskComponent do <%= live_component(@socket, TaskEditComponent, id: "task_edit:#{@task.id}", - task: @task + task: @task, + plans: @plans )%> <% end %> <% else %> @@ -225,8 +227,23 @@ defmodule TaskEditComponent do <%= error_tag(f, :due_at) %> -
- <%= submit("save", class: "button is-dark is-small") %> +
+ +
+
+ <%= multiple_select(f, + :plans, + Enum.map(@plans, &({&1.name, &1.id})), + selected: Enum.map(@task.plans, &(&1.id)) + ) %> +
+
+
+ +
+
+ <%= submit("save", class: "button is-dark is-small") %> +
diff --git a/lib/planner_web/live/tasks_live.ex b/lib/planner_web/live/tasks_live.ex index 82112d5..71f7d43 100644 --- a/lib/planner_web/live/tasks_live.ex +++ b/lib/planner_web/live/tasks_live.ex @@ -128,6 +128,7 @@ defmodule PlannerWeb.TasksLive do id: :tasks, live_action: @live_action, tasks: @tasks, + plans: @plans, active_plan: @active_plan, active_task: @active_task, route_show_task: @route_show_task, @@ -168,11 +169,11 @@ defmodule PlannerWeb.TasksLive do task = Tasks.get_task!(task_params["id"]) case Tasks.update_task(task, task_params) do - {:ok, task} -> + {:ok, changes} -> # I suspect splicing in the updated task isn't much faster than just refreshing the whole list socket = socket - |> refresh_tasks_and_flash_msg("task \"#{task.value}\" updated") + |> refresh_tasks_and_flash_msg("task \"#{changes.task.value}\" updated") route = get_index_route(socket)