NEW: plans (#33)

Fixes #9
This commit is contained in:
Matthew Ryan Dillon 2020-08-23 15:19:10 -07:00 committed by GitHub
parent 177067ab00
commit 9af0124138
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 608 additions and 60 deletions

View file

@ -21,7 +21,7 @@ defmodule TasksComponent do
~L"""
<div class="content">
<%= f = form_for(@changeset, "#", [phx_submit: "new-task"]) %>
<div class="field">
<div id="adder" class="field">
<div class="control">
<%= text_input(f,
:value,
@ -33,6 +33,17 @@ defmodule TasksComponent do
</div>
</form>
<%= if(!is_nil(@active_plan)) do %>
<div
id="deleter"
phx-hook="DeleteDropper"
data-drop="<%= @active_plan.id %>"
class="has-background-danger"
style="height: 38px; width: 100%"
hidden=true
></div>
<% end %>
<ul class="tasks">
<%= for task <- @tasks do %>
<%= live_component(@socket,
@ -73,7 +84,7 @@ defmodule TaskComponent do
<div class="ml-5-5">
<%= if(@is_active) do %>
<%= case @live_action do %>
<% :show -> %>
<% :show_task -> %>
<%= live_component(@socket,
TaskDetailsComponent,
id: "task_details:#{@task.id}",
@ -81,7 +92,7 @@ defmodule TaskComponent do
route_index_tasks: @route_index_tasks,
route_edit_task: @route_edit_task
)%>
<% :edit -> %>
<% :edit_task -> %>
<%= live_component(@socket,
TaskEditComponent,
id: "task_edit:#{@task.id}",
@ -92,7 +103,7 @@ defmodule TaskComponent do
<%= live_patch(to: @route_show_task.(@socket, @task.id),
style: "display: block;"
) do %>
<div class="value ">
<div class="value">
<%= md_to_html(@task.value) %>
</div>
<% end %>
@ -116,7 +127,7 @@ defmodule TaskDetailsComponent do
def render(assigns) do
~L"""
<div class="box">
<div class="box" id="task-details-<%= @task.id %>" draggable="true" phx-hook="Dragger" data-task-id="<%= @task.id %>">
<%= live_patch("",
to: @route_index_tasks.(@socket),
class: "delete is-pulled-right"

View file

@ -2,48 +2,165 @@ defmodule PlannerWeb.TasksLive do
use PlannerWeb, :live_view
alias Planner.Tasks
alias Planner.Tasks.Plan
def mount(_params, _session, socket) do
socket =
socket
|> assign(:tasks, Tasks.list_unfinished_tasks())
|> assign(:active_task, nil)
{:ok, socket}
socket
|> assign(:plans, Tasks.list_unfinished_plans())
|> assign(:plan_changeset, Tasks.change_plan(%Plan{}))
{:ok, socket}
end
def handle_params(%{"task_id" => task_id}, _, socket) do
case Tasks.verify_task_id_from_url(task_id) do
true -> {:noreply, assign(socket, :active_task, task_id)}
_ -> {:noreply, push_patch(socket, to: Routes.tasks_path(socket, :index))}
# plan: yes, task: yes
def handle_params(%{"plan_id" => plan_id, "task_id" => task_id}, _, socket) do
case Tasks.verify_plan_id_from_url(plan_id) and Tasks.verify_task_id_from_url(task_id) do
true ->
socket =
socket
|> assign(:active_task, task_id)
|> assign(:active_plan, Tasks.get_plan!(plan_id))
|> assign(:tasks, Tasks.list_unfinished_tasks_by_plan_id(plan_id))
|> add_plan_routes(plan_id)
{:noreply, socket}
_ ->
{:noreply, push_patch(socket, to: Routes.tasks_path(socket, :index))}
end
end
# plan: no, task: yes
def handle_params(%{"task_id" => task_id}, _, socket) do
case Tasks.verify_task_id_from_url(task_id) do
true ->
socket =
socket
|> assign(:active_task, task_id)
|> assign(:active_plan, nil)
|> assign(:tasks, Tasks.list_unfinished_tasks())
|> add_task_routes()
{:noreply, assign(socket, :active_task, task_id)}
_ ->
{:noreply, push_patch(socket, to: Routes.tasks_path(socket, :index))}
end
end
# plan: yes, task: no
def handle_params(%{"plan_id" => plan_id}, _, socket) do
case Tasks.verify_plan_id_from_url(plan_id) do
true ->
socket =
socket
|> assign(:active_task, nil)
|> assign(:active_plan, Tasks.get_plan!(plan_id))
|> assign(:tasks, Tasks.list_unfinished_tasks_by_plan_id(plan_id))
|> add_plan_routes(plan_id)
{:noreply, socket}
_ ->
{:noreply, push_patch(socket, to: Routes.tasks_path(socket, :index))}
end
end
# plan: no, task: no
def handle_params(_, _, socket) do
{:noreply, assign(socket, :active_task, nil)}
socket =
socket
|> assign(:active_task, nil)
|> assign(:active_plan, nil)
|> assign(:tasks, Tasks.list_unfinished_tasks())
|> add_task_routes()
{:noreply, socket}
end
def render(assigns) do
~L"""
<div phx-window-keydown="keydown" phx-key="Escape">
<%= live_component(@socket,
TasksComponent,
id: :all_unfinished_tasks,
live_action: @live_action,
tasks: @tasks,
active_task: @active_task,
route_show_task: &(Routes.tasks_path(&1, :show, &2)),
route_edit_task: &(Routes.tasks_path(&1, :edit, &2)),
route_index_tasks: &(Routes.tasks_path(&1, :index))
)%>
<div class="columns" phx-window-keydown="keydown" phx-key="Escape">
<div class="column is-one-quarter">
<h4 class="title is-4">plans</h4>
<nav class="panel">
<%= f = form_for(@plan_changeset, "#", phx_submit: "new-plan", class: "panel-block") %>
<div class="control">
<%= text_input(f,
:name,
placeholder: "add new plan",
class: "input", autocomplete: "off"
)%>
<%= error_tag(f, :name) %>
</div>
</form>
<%= live_patch("all unfinished tasks", to: Routes.tasks_path(@socket, :index), class: "panel-block") %>
<%= for plan <- @plans do %>
<%= live_patch(
plan.name,
to: Routes.tasks_path(@socket, :show_plan, plan.id),
class: "panel-block",
phx_hook: "AddDropper",
data_plan_id: plan.id
) %>
<% end %>
</nav>
</div>
<div class="column">
<%= case @active_plan do %>
<%= nil -> %>
<h4 class="title is-4">all unfinished tasks</h4>
<% _ -> %>
<h4 class="title is-4">
<button
type="button"
role="checkbox"
class="doit"
phx-click="finish-plan"
phx-value-plan-id="<%= @active_plan.id %>">
</button>
&nbsp;
<%= @active_plan.name %>
</h4>
<% end %>
<%= live_component(@socket,
TasksComponent,
id: :tasks,
live_action: @live_action,
tasks: @tasks,
active_plan: @active_plan,
active_task: @active_task,
route_show_task: @route_show_task,
route_edit_task: @route_edit_task,
route_index_tasks: @route_index_tasks
)%>
</div>
</div>
"""
end
def handle_event("new-plan", %{"plan" => plan_params}, socket) do
case Tasks.create_plan(plan_params) do
{:ok, _plan} ->
{:noreply, assign(socket, plans: Tasks.list_unfinished_plans())}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, plan_changeset: changeset)}
end
end
def handle_event("finish-plan", %{"plan-id" => plan_id}, socket) do
{_, plan} = Tasks.finish_plan_by_id!(plan_id)
socket = put_flash(socket, :info, "finished plan \"#{plan.name}\"")
socket = assign(socket, plans: Tasks.list_unfinished_plans())
{:noreply, push_patch(socket, to: Routes.tasks_path(socket, :index))}
end
def handle_event("keydown", _params, socket) do
route = get_index_route(socket)
case socket.assigns.live_action do
:index -> {:noreply, socket}
_ -> {:noreply, push_patch(socket, to: Routes.tasks_path(socket, :index))}
_ -> {:noreply, push_patch(socket, to: route)}
end
end
@ -57,7 +174,9 @@ defmodule PlannerWeb.TasksLive do
socket
|> refresh_tasks_and_flash_msg("task \"#{task.value}\" updated")
{:noreply, push_patch(socket, to: Routes.tasks_path(socket, :show, task.id))}
route = get_index_route(socket)
{:noreply, push_patch(socket, to: route)}
{:error, changeset} ->
send_update(TaskEditComponent, id: "task_edit:#{task.id}", changeset: changeset)
@ -72,27 +191,83 @@ defmodule PlannerWeb.TasksLive do
def handle_event("delete-task", %{"task-id" => task_id}, socket) do
{_, task} = Tasks.delete_task_by_id!(task_id)
{:noreply, refresh_tasks_and_flash_msg(socket, "task \"#{task.value}\" deleted")}
socket = refresh_tasks_and_flash_msg(socket, "task \"#{task.value}\" deleted")
route = get_index_route(socket)
{:noreply, push_patch(socket, to: route)}
end
def handle_event("new-task", %{"task" => task_params}, socket) do
add_new_task(task_params, socket.assigns.active_plan, socket)
end
def handle_event("add-task-to-plan", plan_detail_params, socket) do
{_, pd} = Tasks.create_plan_detail(plan_detail_params)
{:noreply,
refresh_tasks_and_flash_msg(socket, "task #{pd.task_id} added to plan #{pd.plan_id}")}
end
def handle_event("delete-task-from-plan", %{"task_id" => task_id, "plan_id" => plan_id}, socket) do
plan_detail = Tasks.get_plan_detail_by!(task_id: task_id, plan_id: plan_id)
{_, pd} = Tasks.delete_plan_detail(plan_detail)
{:noreply,
refresh_tasks_and_flash_msg(socket, "task #{pd.task_id} removed from plan #{pd.plan_id}")}
end
defp refresh_tasks_and_flash_msg(socket, msg) do
tasks =
case socket.assigns.active_plan do
nil -> Tasks.list_unfinished_tasks()
plan -> Tasks.list_unfinished_tasks_by_plan_id(plan.id)
end
socket
|> assign(:tasks, tasks)
|> put_flash(:info, msg)
end
defp add_new_task(task_params, active_plan = nil, socket) do
case Tasks.create_task(task_params) do
{:ok, task} ->
socket =
socket
|> refresh_tasks_and_flash_msg("task \"#{task.value}\" created")
{:noreply, push_patch(socket, to: Routes.tasks_path(socket, :show, task.id))}
{:noreply, refresh_tasks_and_flash_msg(socket, "task \"#{task.value}\" created")}
{:error, %Ecto.Changeset{} = changeset} ->
send_update(TasksComponent, id: :all_unfinished_tasks, changeset: changeset)
send_update(TasksComponent, id: :tasks, changeset: changeset)
{:noreply, socket}
end
end
defp refresh_tasks_and_flash_msg(socket, msg) do
defp add_new_task(task_params, active_plan, socket) do
case Tasks.create_task_and_add_to_plan(task_params, active_plan) do
{:ok, %{plan_detail: _, task: task}} ->
{:noreply, refresh_tasks_and_flash_msg(socket, "task \"#{task.value}\" created")}
{:error, :task, %Ecto.Changeset{} = changeset, _} ->
send_update(TasksComponent, id: :tasks, changeset: changeset)
{:noreply, socket}
end
end
defp add_plan_routes(socket, plan_id) do
socket
|> assign(:tasks, Tasks.list_unfinished_tasks())
|> put_flash(:info, msg)
|> assign(:route_show_task, &Routes.tasks_path(&1, :show_task, plan_id, &2))
|> assign(:route_edit_task, &Routes.tasks_path(&1, :edit_task, plan_id, &2))
|> assign(:route_index_tasks, &Routes.tasks_path(&1, :show_plan, plan_id))
end
defp add_task_routes(socket) do
socket
|> assign(:route_show_task, &Routes.tasks_path(&1, :show_task, &2))
|> assign(:route_edit_task, &Routes.tasks_path(&1, :edit_task, &2))
|> assign(:route_index_tasks, &Routes.tasks_path(&1, :index))
end
defp get_index_route(socket) do
case socket.assigns.active_plan do
nil -> Routes.tasks_path(socket, :index)
plan -> Routes.tasks_path(socket, :show_plan, plan.id)
end
end
end

View file

@ -53,8 +53,12 @@ defmodule PlannerWeb.Router do
pipe_through([:browser, :require_authenticated_user])
live("/", TasksLive, :index)
live("/:task_id", TasksLive, :show)
live("/:task_id/edit", TasksLive, :edit)
live("/tasks", TasksLive, :index)
live("/tasks/:task_id", TasksLive, :show_task)
live("/tasks/:task_id/edit", TasksLive, :edit_task)
live("/plans/:plan_id/tasks", TasksLive, :show_plan)
live("/plans/:plan_id/tasks/:task_id", TasksLive, :show_task)
live("/plans/:plan_id/tasks/:task_id/edit", TasksLive, :edit_task)
get("/users/settings", UserSettingsController, :edit)
put("/users/settings/update_password", UserSettingsController, :update_password)