<.focus_wrap id={"#{@id}-container"} phx-click-away={JS.exec("phx-cancel", to: "##{@id}")} class="shadow-zinc-700/10 ring-zinc-700/10 relative hidden rounded-2xl bg-white p-14 shadow-lg ring-1 transition">
@@ -65,6 +65,7 @@ defmodule AtomicWeb.Components.Modal do
)
|> show("##{id}-container")
|> JS.add_class("overflow-hidden", to: "body")
+ |> JS.focus_first(to: "##{id}-container")
end
def hide_modal(js \\ %JS{}, id) do
diff --git a/lib/atomic_web/live/board_live/edit.html.heex b/lib/atomic_web/live/board_live/edit.html.heex
index e6d1c2228..83cf70828 100644
--- a/lib/atomic_web/live/board_live/edit.html.heex
+++ b/lib/atomic_web/live/board_live/edit.html.heex
@@ -1 +1 @@
-<.live_component module={AtomicWeb.BoardLive.FormComponent} users={@users} id={@user_organization.id} title={@page_title} action={@live_action} user_organization={@user_organization} return_to={Routes.board_show_path(@socket, :show, @user_organization.organization_id, @user_organization.id)} />
+<.live_component module={AtomicWeb.BoardLive.FormComponent} users={@users} id={@user_organization.id} title={@page_title} action={@live_action} user_organization={@user_organization} return_to={Routes.board_show_path(@socket, :show, @user_organization.organization_id)} />
diff --git a/lib/atomic_web/live/board_live/form_component.ex b/lib/atomic_web/live/board_live/form_component.ex
index 967aae4ee..dc72083a6 100644
--- a/lib/atomic_web/live/board_live/form_component.ex
+++ b/lib/atomic_web/live/board_live/form_component.ex
@@ -1,7 +1,12 @@
defmodule AtomicWeb.BoardLive.FormComponent do
use AtomicWeb, :live_component
+ import AtomicWeb.Components.Forms
+
+ alias Atomic.Accounts
+ alias Atomic.Board
alias Atomic.Organizations
+ alias Phoenix.LiveView.JS
@impl true
def mount(socket) do
@@ -9,62 +14,452 @@ defmodule AtomicWeb.BoardLive.FormComponent do
end
@impl true
- def update(%{user_organization: user_organization} = assigns, socket) do
- changeset = Organizations.change_user_organization(user_organization)
+ def render(assigns) do
+ ~H"""
+
+ <%= forms(assigns) %>
+
+ <.modal :if={@action_modal} id="action-confirm-modal" show on_cancel={JS.push("clear-action", target: @myself)}>
+
+
+ <%= display_action_goal_confirm_title(@action_modal) %>
+
+ <%= if @action_modal in [:delete_board, :delete_department] do %>
+
+ <%= gettext("This action cannot be undone.") %>
+
+ <% end %>
+
+ <.button phx-click="clear-action" class="mr-2" phx-target={@myself} size={:lg} icon={:x_circle} color={:white} full_width>Cancel
+ <.button
+ phx-click="confirm"
+ class="ml-2"
+ phx-target={@myself}
+ size={:lg}
+ icon={:check_circle}
+ color={
+ if @action_modal in [:delete_board, :delete_department] do
+ :danger
+ else
+ :success
+ end
+ }
+ full_width
+ >
+ Confirm
+
+
+
+
+
+ """
+ end
+
+ @impl true
+ def update(%{organization_id: _org} = assigns, socket) do
+ changeset =
+ case assigns.action do
+ :new_board ->
+ Board.change_board(%Organizations.Board{})
+
+ :edit_board ->
+ Board.change_board(assigns.board)
+
+ :new_department ->
+ Board.change_board_department(%Organizations.BoardDepartments{})
+
+ :edit_department ->
+ Board.change_board_department(Board.get_board_department!(assigns.department_id))
+
+ _ ->
+ Board.change_board(assigns.board)
+ end
+
+ # changeset = Board.change_board(assigns.board)
+ # users = Enum.map(Accounts.list_users(), fn u -> [key: u.email, value: u.id] end)
+ hide_dropdown()
+ # users = Accounts.list_users()
+ users = %{}
{:ok,
socket
|> assign(assigns)
+ |> assign(:action_modal, nil)
+ |> assign(users: users)
|> assign(:changeset, changeset)}
end
@impl true
- def handle_event("validate", %{"user_organization" => user_organization_params}, socket) do
+ def handle_event("validate", %{"board" => board_params}, socket) do
changeset =
socket.assigns.user_organization
- |> Organizations.change_user_organization(user_organization_params)
+ # |> Organizations.change_user_organization(user_organization_params)
+ |> Board.change_board(board_params)
|> Map.put(:action, :validate)
{:noreply, assign(socket, :changeset, changeset)}
end
- def handle_event("save", %{"user_organization" => user_organization_params}, socket) do
- save_user_organization(socket, socket.assigns.action, user_organization_params)
+ @impl true
+ def handle_event("clear-action", _, socket) do
+ {:noreply,
+ socket
+ |> assign(:action_modal, nil)}
+ end
+
+ @impl true
+ def handle_event("save", board_params, socket) do
+ # save_user_organization(socket, socket.assigns.action, user_organization_params)
+ IO.inspect("called save")
+
+ case socket.assigns.action do
+ :new_board -> save_board(socket, :new, board_params)
+ :edit_board -> save_board(socket, :edit, board_params)
+ :new_department -> save_department(socket, :new, board_params)
+ :edit_department -> save_department(socket, :edit, board_params)
+ end
+ end
+
+ @impl true
+ def handle_event("update_department", board_params, socket) do
+ users =
+ Enum.filter(Accounts.list_users(), fn u ->
+ String.starts_with?(String.downcase(u.name), board_params["board"]["users"])
+ end)
+
+ # show_dropdown()
+
+ {:noreply,
+ socket
+ |> assign(:users, users)}
+ end
+
+ @impl true
+ def handle_event(action, _, socket) when action in ["delete_board", "delete_department"] do
+ IO.inspect(action)
+
+ {:noreply,
+ socket
+ |> assign(:action_modal, String.to_atom(action))}
+ end
+
+ @impl true
+ def handle_event("confirm", _, socket) do
+ case socket.assigns.action_modal do
+ # :confirm_request -> accept_collaborator_request(socket)
+ # :deny_request -> deny_collaborator_request(socket)
+ :delete_board -> save_board(socket, :delete, socket.assigns.board)
+ :delete_department -> save_department(socket, :delete, socket.assigns.department_id)
+ end
+ end
+
+ @impl true
+ def handle_event("remove_user", %{"user-id" => user_id}, socket) do
+ IO.inspect(user_id)
+
+ IO.puts("Remove user")
+
+ {:noreply, assign(socket, :users, Board.get_board_department_users(socket.assigns.department_id))}
+ end
+
+ defp save_board(socket, :new, board_params) do
+ board_params =
+ Map.put(board_params["board"], "organization_id", socket.assigns.organization_id)
+
+ # board_params = Map.put(%Board{}, "board", board_map)
+
+ IO.inspect(board_params)
+
+ case Board.create_board(board_params) do
+ {:ok, board} ->
+ {:noreply,
+ socket
+ |> put_flash(:success, "Board created successfully")
+ |> push_navigate(
+ to: Routes.board_index_path(socket, :show, socket.assigns.organization_id, board.id)
+ )}
+
+ {:error, %Ecto.Changeset{} = changeset} ->
+ {:noreply, assign(socket, changeset: changeset)}
+ end
+ end
+
+ defp save_board(socket, :edit, %{"board" => board_params}) do
+ # board_params = Map.put(board_params, "organization_id", socket.assigns.organization_id)
+ board = Board.get_board!(socket.assigns.board.id)
+ IO.inspect(board)
+ IO.puts("Edit board")
+
+ case Board.update_board(board, board_params) do
+ {:ok, _board} ->
+ {:noreply,
+ socket
+ |> put_flash(:success, "Board edited successfully")
+ |> push_patch(to: socket.assigns.return_to)}
+
+ {:error, %Ecto.Changeset{} = changeset} ->
+ {:noreply, assign(socket, changeset: changeset)}
+ end
end
- defp save_user_organization(socket, :edit, user_organization_params) do
- case Organizations.update_user_organization(
- socket.assigns.user_organization,
- user_organization_params
- ) do
- {:ok, _organization} ->
+ defp save_board(socket, :delete, _board_params) do
+ board = Board.get_board!(socket.assigns.board.id)
+ IO.inspect(socket.assigns.return_to)
+
+ case Board.delete_board(board) do
+ {:ok, _board} ->
{:noreply,
socket
- |> put_flash(:info, "Board updated successfully")
+ |> put_flash(:success, "Board deleted successfully")
+ |> assign(
+ :return_to,
+ Routes.board_index_path(socket, :index, socket.assigns.organization_id)
+ )
|> push_navigate(to: socket.assigns.return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
- {:noreply, assign(socket, :changeset, changeset)}
+ {:noreply, assign(socket, changeset: changeset)}
+ end
+ end
+
+ defp save_department(socket, :new, department_params) do
+ # department_params =
+ # Map.put(department_params, "board", socket.assigns.board)
+
+ # board_params = Map.put(%Board{}, "board", board_map)
+ department_params =
+ Map.put(department_params["board_departments"], "board_id", socket.assigns.board.id)
+ |> Map.put("priority", 1)
+
+ IO.inspect(department_params)
+
+ case Board.create_board_department(department_params) do
+ {:ok, board_deparment} ->
+ {:noreply,
+ socket
+ |> put_flash(:success, "Department created successfully")
+ |> push_navigate(
+ to:
+ Routes.board_index_path(
+ socket,
+ :show,
+ socket.assigns.organization_id,
+ socket.assigns.board.id
+ )
+ )}
+
+ {:error, %Ecto.Changeset{} = changeset} ->
+ {:noreply, assign(socket, changeset: changeset)}
+ end
+ end
+
+ defp save_department(socket, :edit, department_params) do
+ # department_params =
+ # Map.put(department_params["board_departments"], "board_id", socket.assigns.board.id)
+ department_params = department_params["board_departments"]
+ department = Board.get_board_department!(socket.assigns.department_id)
+ # board_params = Map.put(%Board{}, "board", board_map)
+
+ IO.inspect(department_params)
+
+ case Board.update_board_department(department, department_params) do
+ {:ok, board_department} ->
+ {:noreply,
+ socket
+ |> put_flash(:success, "Department updated successfully")
+ |> push_navigate(
+ to:
+ Routes.board_index_path(
+ socket,
+ :show,
+ socket.assigns.organization_id,
+ socket.assigns.board.id
+ )
+ )}
+
+ {:error, %Ecto.Changeset{} = changeset} ->
+ {:noreply, assign(socket, changeset: changeset)}
end
end
- defp save_user_organization(socket, :new, user_organization_params) do
- attrs =
- Map.put(
- user_organization_params,
- "organization_id",
- socket.assigns.user_organization.organization_id
- )
+ defp save_department(socket, :delete, _department_params) do
+ department = Board.get_board_department!(socket.assigns.department_id)
+ IO.inspect("called delete department")
- case Organizations.create_user_organization(attrs) do
- {:ok, _organization} ->
+ case Board.delete_board_department(department) do
+ {:ok, _board} ->
{:noreply,
socket
- |> put_flash(:info, "Board created successfully")
+ |> put_flash(:success, "Department deleted successfully")
+ |> assign(
+ :return_to,
+ Routes.board_index_path(
+ socket,
+ :show,
+ socket.assigns.organization_id,
+ socket.assigns.board.id
+ )
+ )
|> push_navigate(to: socket.assigns.return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, changeset: changeset)}
end
end
+
+ defp forms(%{action: action} = assigns) when action in [:new_board, :edit_board] do
+ ~H"""
+
<%= @title %>
+
+ <.form :let={f} for={@changeset} id="board-form" phx-target={@myself} phx-submit="save">
+ <%!-- <%= label(f, :user_id) %> --%>
+ <%!-- <%= select(f, :user_id, @users) %> --%>
+ <%!-- <%= label(f, :title) %> --%>
+ <%!-- <%= text_input(f, :title) %> --%>
+
+ <.field field={f[:name]} id="name" label="Name" type="text" placeholder="Board name" />
+
+
+
+ <%= if @action in [:edit_board] do %>
+ <.button size={:md} color={:danger} icon={:trash} type="button" phx-click="delete_board" phx-target={@myself}>Delete board
+ <% end %>
+ <.button size={:md} color={:white} icon={:check}>Save Changes
+
+
+ """
+ end
+
+ defp forms(%{action: action} = assigns) when action in [:new_department, :edit_department] do
+ ~H"""
+
+ <%= if action == :new_department do %>
+ New Department
+ <% else %>
+ Edit Department
+ <% end %>
+
+
+ <.form :let={f} id="department-form" for={@changeset} phx-target={@myself} phx-submit="save">
+ <%!-- <%= label(f, :user_id) %> --%>
+ <%!-- <%= select(f, :user_id, @users) %> --%>
+ <%!-- <%= label(f, :title) %> --%>
+ <%!-- <%= text_input(f, :title) %> --%>
+
+
+ <%= label(f, :name, class: "text-sm font-semibold") %>
+
The name of the department
+
+ <%= text_input(f, :name, class: "rounded-lg border-zinc-200 focus:ring-primary-500 focus:border-primary-500") %>
+ <%= error_tag(f, :name) %>
+
+
+
+
+ <%= label(f, :users, class: "text-sm font-semibold") %>
+
The name of the department
+
+ <%!-- <%= select(f, :user_id, @users, class: "rounded-lg border-zinc-200 focus:ring-primary-500 focus:border-primary-500") %> --%>
+ <%!-- <.live_component module={MultiSelect} id="users" items={@users} selected_items={[]} target={@myself} /> --%>
+
+ <%= text_input(f, :users, class: "rounded-lg border-zinc-200 focus:ring-primary-500 focus:border-primary-500", phx_click: show_dropdown(), phx_change: "update_department", phx_target: @myself, autocomplete: "off", id: "department-users-input") %>
+
+ <%= if Board.get_board_department_users(@department_id) == {} do %>
+
Empty...
+ <% end %>
+
+
+ <%= for user_organization <- Board.get_board_department_users(@department_id) do %>
+ -
+
+
<%= user_organization.user.name %>
+ <.button color={:light} type="button" phx-target={@myself} phx-click="remove_user" phx-value-user-id={user_organization.user.id} class="max-h-8">
+
+ <.icon name={:trash} />
+
+
+
+
+ <% end %>
+
+
+
+
+ <%!--
--%>
+
+ <%= error_tag(f, :users) %>
+
+
+
+ <%= if @action in [:edit_department] do %>
+ <.button size={:md} color={:danger} icon={:trash} type="button" phx-click="delete_department" phx-target={@myself} full_width>Delete department
+ <% end %>
+ <.button size={:md} color={:white} icon={:check} full_width>Save Changes
+
+
+ """
+ end
+
+ defp display_action_goal_confirm_title(action) do
+ case action do
+ :confirm_request ->
+ gettext("Are you sure you want to accept this request?")
+
+ :deny_request ->
+ gettext("Are you sure you want to deny this request?")
+
+ :delete_board ->
+ gettext("Are you sure you want to remove this board?")
+
+ :delete_department ->
+ gettext("Are you sure you want to remove this department?")
+
+ _ ->
+ gettext("Are you sure you want to perform this action?")
+ end
+ end
+
+ defp display_action_goal_confirm_description(action, board) do
+ case action do
+ :confirm_request ->
+ gettext("If you change your mind you can always remove this person later.")
+
+ :deny_request ->
+ gettext("If you deny this request, this person will not get access to the department.")
+
+ :delete_board ->
+ gettext(
+ "If you remove this person, they will no longer have access to %{department_name}.",
+ department_name: board.name
+ )
+ end
+ end
+
+ defp hide_dropdown(js \\ %JS{}) do
+ js
+ |> JS.remove_class("rounded-t-lg", to: "#department-users-input")
+ |> JS.add_class("rounded-lg", to: "#department-users-input")
+ |> JS.hide(
+ transition: {"ease-in duration-150", "scale-y-100", "scale-y-0"},
+ to: "#department-users-dropdown"
+ )
+ end
+
+ defp show_dropdown(js \\ %JS{}) do
+ js
+ |> JS.remove_class("rounded-lg", to: "#department-users-input")
+ |> JS.add_class("rounded-t-lg", to: "#department-users-input")
+ |> JS.show(
+ transition: {"ease-out duration-150", "scale-y-0", "scale-y-100"},
+ to: "#department-users-dropdown"
+ )
+ end
end
diff --git a/lib/atomic_web/live/board_live/form_component.html.heex b/lib/atomic_web/live/board_live/form_component.html.heex
deleted file mode 100644
index 9537729f4..000000000
--- a/lib/atomic_web/live/board_live/form_component.html.heex
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
<%= @title %>
-
- <.form :let={f} for={@changeset} id="board-form" phx-target={@myself} phx-submit="save">
- <%= label(f, :user_id) %>
- <%= select(f, :user_id, @users) %>
- <%= label(f, :title) %>
- <%= text_input(f, :title) %>
- <%= label(f, :year) %>
- <%= text_input(f, :year, pattern: "\\d{4}/\\d{4}") %>
- <%= submit("Save", phx_disable_with: "Saving...") %>
-
-
diff --git a/lib/atomic_web/live/board_live/index.ex b/lib/atomic_web/live/board_live/index.ex
index 3e2a2c6b8..ba94acca0 100644
--- a/lib/atomic_web/live/board_live/index.ex
+++ b/lib/atomic_web/live/board_live/index.ex
@@ -2,13 +2,17 @@ defmodule AtomicWeb.BoardLive.Index do
use AtomicWeb, :live_view
import AtomicWeb.Components.Empty
+ import AtomicWeb.Components.Avatar
import AtomicWeb.Components.Board
import AtomicWeb.Components.Button
+ import AtomicWeb.Components.Icon
+ import AtomicWeb.Components.Modal
alias Atomic.Accounts
alias Atomic.Board
alias Atomic.Ecto.Year
alias Atomic.Organizations
+ alias Phoenix.LiveView.JS
@impl true
def mount(_params, _session, socket) do
@@ -16,9 +20,18 @@ defmodule AtomicWeb.BoardLive.Index do
end
@impl true
- def handle_params(%{"organization_id" => organization_id}, _, socket) do
+ def handle_params(%{"organization_id" => organization_id} = params, _, socket) do
+ board_id = Map.get(params, "id")
+ department_id = Map.get(params, "department_id")
+
current_year = Year.current_year()
- board = Board.get_organization_board_by_year(current_year, organization_id)
+ boards = Board.list_boards_by_organization_id(organization_id)
+
+ board =
+ case board_id do
+ nil -> Board.get_organization_board_by_year(current_year, organization_id)
+ _ -> Board.get_board!(board_id)
+ end
board_departments =
case board do
@@ -38,7 +51,11 @@ defmodule AtomicWeb.BoardLive.Index do
|> assign(:has_permissions?, has_permissions?(socket, organization_id))
|> assign(:organization, organization)
|> assign(:role, role)
- |> assign(:year, current_year)}
+ |> assign(:boards, boards)
+ |> assign(:board, board)
+ |> assign(:params, params)
+ |> assign(:year, current_year)
+ |> assign(:department_id, department_id)}
end
@impl true
@@ -77,6 +94,23 @@ defmodule AtomicWeb.BoardLive.Index do
|> assign(:year, year)}
end
+ @impl true
+ def handle_event("update-selected-board", %{"id" => id}, socket) do
+ board = Board.get_board!(id)
+
+ board_departments =
+ case board do
+ nil -> []
+ _ -> Board.get_board_departments_by_board_id(board.id)
+ end
+
+ {:noreply,
+ socket
+ |> assign(:board_departments, board_departments)
+ |> assign(:empty?, Enum.empty?(board_departments))
+ |> push_patch(to: Routes.board_index_path(socket, :show, socket.assigns.organization.id, id))}
+ end
+
@impl true
def handle_event("update-sorting", %{"ids" => ids}, socket) do
ids = Enum.filter(ids, fn id -> String.length(id) > 0 end)
@@ -92,6 +126,24 @@ defmodule AtomicWeb.BoardLive.Index do
{:noreply, socket}
end
+ @impl true
+ def handle_info({:change_collaborator, %{status: status, message: message}}, socket) do
+ {:noreply,
+ socket
+ |> put_flash(status, message)
+ |> assign(:live_action, :show)
+ |> push_patch(
+ to:
+ Routes.department_show_path(
+ socket,
+ :show,
+ socket.assigns.organization,
+ socket.assigns.department,
+ Map.delete(socket.assigns.params, "collaborator_id")
+ )
+ )}
+ end
+
defp has_permissions?(socket, organization_id) do
Accounts.has_master_permissions?(socket.assigns.current_user.id) ||
Accounts.has_permissions_inside_organization?(
diff --git a/lib/atomic_web/live/board_live/index.html.heex b/lib/atomic_web/live/board_live/index.html.heex
index 84226c333..50d91d21e 100644
--- a/lib/atomic_web/live/board_live/index.html.heex
+++ b/lib/atomic_web/live/board_live/index.html.heex
@@ -1,47 +1,95 @@
-
-
-
-
- <.icon name={:arrow_small_left} solid class="cursor-pointer mb-2 mr-2 w-8 h-8 text-zinc-400" phx-click="previous-year" phx-value-organization_id={@organization.id} />
-
- <%= gettext("Board") %> <%= @year %>
-
- <.icon name={:arrow_small_right} solid class="cursor-pointer mb-2 ml-2 w-8 h-8 text-zinc-400" phx-click="next-year" phx-value-organization_id={@organization.id} />
-
- <%= if not @empty? and @has_permissions? do %>
-
- <.button navigate={Routes.board_new_path(@socket, :new, @organization)}>
- + <%= gettext("New Board Member") %>
+<.page title="Board">
+ <:actions>
+ <%= if @has_permissions? do %>
+ <.button icon={:plus} icon_class="stroke-2" patch={Routes.board_index_path(@socket, :new_board, @organization)}>
+ <%= gettext("New Board") %>
+
+ <% end %>
+
+ <%= if @has_permissions? do %>
+
+
+
+ <.button patch={Routes.board_index_path(@socket, :edit_board, @organization, @board.id)} color={:light} class="border-none">
+ <.icon name={:pencil} solid class="h-5 w-5 text-zinc-400" />
+
+
+
+ <%= if not @empty? do %>
+
+
+ <%= length(@board_departments) %> departments in your organization
+ <.button patch={Routes.board_index_path(@socket, :new_department, @organization, @board.id)} color={:light} variant={:outline}>
+ <.icon name={:plus} solid class="h-4 w-4 text-zinc-400" />
- <% end %>
-
- <%= if @empty? and @has_permissions? do %>
-
- <.empty_state url={Routes.board_new_path(@socket, :new, @organization)} placeholder="board member" />
+
+ <%= for board_department <- @board_departments do %>
+ -
+
+
+
+ <.icon name={:bars_3} solid class="h-5 w-5 text-zinc-400" />
+
+
<%= board_department.name %>
+
+
+
+
+ <%= for user_organization <- Board.get_board_department_users(board_department.id, preloads: [:user]) |> Enum.take(4) do %>
+ <.avatar class="mx-auto ring-1 ring-white" color={:light_gray} name={user_organization.user.name} size={:xs} src={Uploaders.ProfilePicture.url({user_organization.user.profile_picture, user_organization.user}, :original)} />
+ <% end %>
+ <%= if length(Board.get_board_department_users(board_department.id, preloads: [:user])) > 4 do %>
+ <%!-- Uncomment this after improve departments pages is merged (auto_generate_initials) --%>
+ <%!-- <.avatar name={"+#{length(Board.get_board_department_users(board_department.id, preloads: [:user])) - 4}"} size={:xs} auto_generate_initials={false} color={:light_gray} class="ring-1 ring-white" /> --%>
+ <.avatar name={"+#{length(Board.get_board_department_users(board_department.id, preloads: [:user])) - 4}"} size={:xs} color={:light_gray} class="ring-1 ring-white" />
+ <% end %>
+
+
+
+
+
+ <%= length(Board.get_board_department_users(board_department.id, preloads: [:user])) %> members
+
+ <.button patch={Routes.board_index_path(@socket, :edit_department, @organization, @board.id, board_department, @params)} color={:light} class="max-h-8">
+
+ <.icon name={:pencil} />
+
+
+
+ <% end %>
+
<% else %>
- <%= for board_department <- @board_departments do %>
-
-
-
- <%= if @role in [:owner, :admin] do %>
-
- <.icon name={:bars_3} solid class="w-5 h-5 text-zinc-400" />
-
- <% end %>
-
<%= board_department.name %>
-
-
-
-
- <%= for user_organization <- Board.get_board_department_users(board_department.id, preloads: [:user]) do %>
- <.member_bubble user_organization={user_organization} />
- <% end %>
-
+
+ <.empty_state url={Routes.board_index_path(@socket, :new_department, @organization, @board)} placeholder="board member" />
+
+ <% end %>
+ <% else %>
+ <%= for board_department <- @board_departments do %>
+
-
+
+
<%= board_department.name %>
+
+
+
+
+ <%= for user_organization <- Board.get_board_department_users(board_department.id, preloads: [:user]) do %>
+ <.member_bubble user_organization={user_organization} />
+ <% end %>
-
- <% end %>
+
+
<% end %>
-
-
+ <% end %>
+
+<.modal :if={@live_action in [:new_board, :edit_board, :new_department, :edit_department]} id="board-modal" show on_cancel={JS.patch(Routes.board_index_path(@socket, :show, @organization, @board))}>
+ <.live_component module={AtomicWeb.BoardLive.FormComponent} organization_id={@organization.id} department_id={@department_id} board={@board} id="board-forms" action={@live_action} title={@page_title} return_to={Routes.board_index_path(@socket, :show, @current_organization, @board)} />
+
diff --git a/lib/atomic_web/live/board_live/new.ex b/lib/atomic_web/live/board_live/new.ex
index bda0bf760..424d63c76 100644
--- a/lib/atomic_web/live/board_live/new.ex
+++ b/lib/atomic_web/live/board_live/new.ex
@@ -2,7 +2,6 @@ defmodule AtomicWeb.BoardLive.New do
@moduledoc false
use AtomicWeb, :live_view
- alias Atomic.Accounts
alias Atomic.Organizations.UserOrganization
@impl true
@@ -11,12 +10,14 @@ defmodule AtomicWeb.BoardLive.New do
end
@impl true
- def handle_params(%{"organization_id" => _organization_id}, _, socket) do
+ def handle_params(%{"organization_id" => organization_id}, _, socket) do
{:noreply,
socket
|> assign(:current_page, :board)
|> assign(:page_title, gettext("New Board"))
|> assign(:user_organization, %UserOrganization{})
- |> assign(:users, Enum.map(Accounts.list_users(), fn u -> [key: u.email, value: u.id] end))}
+ |> assign(:organization_id, organization_id)}
+
+ # |> assign(:users, Enum.map(Accounts.list_users(), fn u -> [key: u.email, value: u.id] end))}
end
end
diff --git a/lib/atomic_web/live/board_live/new.html.heex b/lib/atomic_web/live/board_live/new.html.heex
index 36b75b43c..98b7eb334 100644
--- a/lib/atomic_web/live/board_live/new.html.heex
+++ b/lib/atomic_web/live/board_live/new.html.heex
@@ -1 +1,3 @@
-<.live_component module={AtomicWeb.BoardLive.FormComponent} organization_id={@current_organization.id} users={@users} id={:new} title={@page_title} action={@live_action} user_organization={@user_organization} return_to={Routes.board_index_path(@socket, :index, @current_organization.id)} />
+<.page title={@page_title}>
+ <.live_component module={AtomicWeb.BoardLive.FormComponent} organization_id={@organization_id} id={:new} title={@page_title} action={@live_action} return_to={Routes.board_index_path(@socket, :index, @current_organization.id)} />
+
diff --git a/lib/atomic_web/router.ex b/lib/atomic_web/router.ex
index 9e319a191..b01fc38de 100644
--- a/lib/atomic_web/router.ex
+++ b/lib/atomic_web/router.ex
@@ -111,8 +111,11 @@ defmodule AtomicWeb.Router do
scope "/board" do
pipe_through :confirm_board_association
- live "/new", BoardLive.New, :new
- live "/:id/edit", BoardLive.Edit, :edit
+ # live "/new", BoardLive.New, :new
+ live "/new", BoardLive.Index, :new_board
+ live "/:id/edit", BoardLive.Index, :edit_board
+ live "/:id/department/new", BoardLive.Index, :new_department
+ live "/:id/department/:department_id/edit", BoardLive.Index, :edit_department
end
scope "/memberships" do
@@ -169,7 +172,7 @@ defmodule AtomicWeb.Router do
scope "/board" do
pipe_through :confirm_board_association
live "/", BoardLive.Index, :index
- live "/:id", BoardLive.Show, :show
+ live "/:id", BoardLive.Index, :show
end
scope "/partners" do
diff --git a/priv/repo/migrations/20230980102641_create_boards.exs b/priv/repo/migrations/20230980102641_create_boards.exs
index 2a1d9e3e5..f79970df4 100644
--- a/priv/repo/migrations/20230980102641_create_boards.exs
+++ b/priv/repo/migrations/20230980102641_create_boards.exs
@@ -4,13 +4,13 @@ defmodule Atomic.Repo.Migrations.CreateBoards do
def change do
create table(:boards, primary_key: false) do
add :id, :binary_id, primary_key: true
- add :year, :string, null: false
+ add :name, :string, null: false
add :organization_id, references(:organizations, type: :binary_id), null: false
timestamps()
end
- create unique_index(:boards, [:year, :organization_id])
+ create unique_index(:boards, [:name, :organization_id])
end
end
diff --git a/priv/repo/seeds/memberships.exs b/priv/repo/seeds/memberships.exs
index 97cd004c5..65bd20e23 100644
--- a/priv/repo/seeds/memberships.exs
+++ b/priv/repo/seeds/memberships.exs
@@ -75,7 +75,7 @@ defmodule Atomic.Repo.Seeds.Memberships do
%Board{}
|> Board.changeset(%{
"organization_id" => organization.id,
- "year" => Year.current_year()
+ "name" => Year.current_year()
})
|> Repo.insert!()
end