Admin direct edit on contact show page, suggest edit for non-admins

This commit is contained in:
Graham McIntire 2026-04-11 16:46:21 -05:00
parent e651c1e481
commit 08ffc7e028
2 changed files with 44 additions and 20 deletions

View file

@ -379,7 +379,8 @@ defmodule Microwaveprop.Radio do
|> Repo.insert()
end
defp normalize_proposed(changes) do
@doc false
def normalize_proposed(changes) do
changes
|> normalize_string_field("station1")
|> normalize_string_field("station2")
@ -396,7 +397,8 @@ defmodule Microwaveprop.Radio do
end
end
defp diff_against_contact(contact, proposed) do
@doc false
def diff_against_contact(contact, proposed) do
Enum.reduce(proposed, %{}, fn {key, new_val}, acc ->
current = current_value(contact, key)
@ -500,7 +502,8 @@ defmodule Microwaveprop.Radio do
|> Repo.update()
end
defp apply_edit_to_contact(contact, proposed_changes) do
@doc "Apply proposed changes directly to a contact (admin use)."
def apply_edit_to_contact(contact, proposed_changes) do
changes = build_contact_changes(contact, proposed_changes)
grids_or_band_changed =

View file

@ -95,6 +95,9 @@ defmodule MicrowavepropWeb.ContactLive.Show do
defp current_user(%{current_scope: %{user: %{} = user}}), do: user
defp current_user(_), do: nil
defp admin?(%{current_scope: %{user: %{is_admin: true}}}), do: true
defp admin?(_), do: false
@impl true
def handle_event("sort", %{"field" => field, "table" => "obs"}, socket) do
{sort_by, sort_order} =
@ -177,25 +180,42 @@ defmodule MicrowavepropWeb.ContactLive.Show do
user = current_user(socket.assigns)
if is_nil(user) do
{:noreply, put_flash(socket, :error, "You must be logged in to suggest edits.")}
{:noreply, put_flash(socket, :error, "You must be logged in to edit.")}
else
contact = socket.assigns.contact
case Radio.create_contact_edit(contact, user, params) do
{:ok, _edit} ->
if admin?(socket.assigns) do
# Admin: apply changes directly
proposed = Radio.diff_against_contact(contact, Radio.normalize_proposed(params))
if proposed == %{} do
{:noreply, put_flash(socket, :error, "No changes detected.")}
else
Radio.apply_edit_to_contact(contact, proposed)
updated = Radio.get_contact!(contact.id)
{:noreply,
socket
|> assign(editing: false, edit_form: nil, pending_edit: Radio.pending_edit_for_user(contact.id, user.id))
|> put_flash(:info, "Edit submitted for review.")}
|> assign(contact: updated, editing: false, edit_form: nil)
|> put_flash(:info, "Contact updated.")}
end
else
case Radio.create_contact_edit(contact, user, params) do
{:ok, _edit} ->
{:noreply,
socket
|> assign(editing: false, edit_form: nil, pending_edit: Radio.pending_edit_for_user(contact.id, user.id))
|> put_flash(:info, "Edit submitted for review.")}
{:error, changeset} ->
messages =
changeset
|> Ecto.Changeset.traverse_errors(fn {msg, _opts} -> msg end)
|> Enum.flat_map(fn {_field, msgs} -> msgs end)
|> Enum.join(", ")
{:error, changeset} ->
messages =
changeset
|> Ecto.Changeset.traverse_errors(fn {msg, _opts} -> msg end)
|> Enum.flat_map(fn {_field, msgs} -> msgs end)
|> Enum.join(", ")
{:noreply, put_flash(socket, :error, "Could not submit edit: #{messages}")}
{:noreply, put_flash(socket, :error, "Could not submit edit: #{messages}")}
end
end
end
end
@ -529,7 +549,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do
name={if @editing, do: "hero-x-mark", else: "hero-pencil-square"}
class="w-4 h-4"
/>
{if @editing, do: "Cancel Edit", else: "Suggest Edit"}
{if @editing, do: "Cancel", else: if(admin?(assigns), do: "Edit", else: "Suggest Edit")}
</button>
<% end %>
<button
@ -548,7 +568,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do
</:actions>
</.header>
<%= if @pending_edit && !@editing do %>
<%= if @pending_edit && !@editing && !admin?(assigns) do %>
<div class="bg-info/10 border border-info/30 rounded-box px-4 py-2 text-sm mb-4">
<.icon name="hero-clock" class="w-4 h-4 inline" />
You have a pending edit for this contact awaiting admin review.
@ -557,9 +577,9 @@ defmodule MicrowavepropWeb.ContactLive.Show do
<%= if @editing do %>
<div class="bg-base-200 rounded-box p-4 mb-4">
<h3 class="font-semibold mb-3">Suggest Edit</h3>
<h3 class="font-semibold mb-3">{if admin?(assigns), do: "Edit Contact", else: "Suggest Edit"}</h3>
<p class="text-sm opacity-70 mb-4">
Change any fields below. Only fields you modify will be submitted for review.
{if admin?(assigns), do: "Change any fields below. Changes will be applied immediately.", else: "Change any fields below. Only fields you modify will be submitted for review."}
</p>
<.form
for={@edit_form}
@ -585,7 +605,8 @@ defmodule MicrowavepropWeb.ContactLive.Show do
</div>
<div class="flex gap-2">
<.button type="submit" class="btn btn-primary btn-sm">
<.icon name="hero-paper-airplane" class="w-4 h-4" /> Submit for Review
<.icon name="hero-paper-airplane" class="w-4 h-4" />
{if admin?(assigns), do: "Save Changes", else: "Submit for Review"}
</.button>
<button type="button" phx-click="toggle_edit" class="btn btn-ghost btn-sm">
Cancel