NEW: form-based many-to-many plans-tasks (#39)

This commit is contained in:
Matthew Ryan Dillon 2020-09-19 15:09:53 -07:00 committed by GitHub
parent 5d91febec5
commit 7cbb884ef0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 8 deletions

View file

@ -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

View file

@ -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,9 +227,24 @@ defmodule TaskEditComponent do
<%= error_tag(f, :due_at) %>
</div>
<div class="field">
<label class="label">plans</label>
<div class="control">
<div class="select is-multiple is-dark">
<%= multiple_select(f,
:plans,
Enum.map(@plans, &({&1.name, &1.id})),
selected: Enum.map(@task.plans, &(&1.id))
) %>
</div>
</div>
</div>
<div class="field">
<div class="control">
<%= submit("save", class: "button is-dark is-small") %>
</div>
</div>
</form>
</div>
"""

View file

@ -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)