feat: stay on add device page after creation for batch adding

- After creating a device, stay on /devices/new instead of navigating to device show page
- Display success flash message with creation confirmation
- Reset form to defaults (preserving selected site) for adding next device
- Allows users to quickly add multiple devices in a row without navigation
- Add tests for staying on page and adding multiple devices sequentially
- All 91 device-related tests passing with no Credo warnings
This commit is contained in:
Graham McIntire 2026-01-17 16:16:10 -06:00
parent 5398ff65bc
commit f27e1622a3
No known key found for this signature in database
2 changed files with 86 additions and 18 deletions

View file

@ -223,10 +223,24 @@ defmodule ToweropsWeb.DeviceLive.Form do
flash_message = handle_device_creation(device)
# Reset form for next device while staying on the add page
fresh_attrs = %{
monitoring_enabled: true,
check_interval_seconds: 300,
snmp_enabled: snmp_enabled,
snmp_version: "2c",
snmp_port: 161,
# Keep the same site selected
site_id: device.site_id
}
fresh_changeset = Devices.change_device(%DeviceSchema{}, fresh_attrs)
{:noreply,
socket
|> put_flash(:info, flash_message)
|> push_navigate(to: ~p"/orgs/#{socket.assigns.organization.slug}/devices/#{device.id}")}
|> assign(:form, to_form(fresh_changeset))
|> assign(:snmp_test_result, nil)}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, :form, to_form(changeset))}

View file

@ -216,27 +216,39 @@ defmodule ToweropsWeb.DeviceLiveTest do
assert html =~ "Add new device to monitor"
end
test "creates new device", %{conn: conn, organization: organization, site: site} do
test "creates new device and stays on add page with success message", %{
conn: conn,
organization: organization,
site: site
} do
{:ok, view, _html} = live(conn, ~p"/orgs/#{organization.slug}/devices/new")
# Default is SNMP & ICMP mode, so snmp fields should be visible
view
|> form("#device-form",
device: %{
name: "New Router",
ip_address: "192.168.1.100",
site_id: site.id,
description: "Test router",
monitoring_enabled: true,
check_interval_seconds: 300,
snmp_version: "2c",
snmp_community: "public",
snmp_port: 161
}
)
|> render_submit()
html =
view
|> form("#device-form",
device: %{
name: "New Router",
ip_address: "192.168.1.100",
site_id: site.id,
description: "Test router",
monitoring_enabled: true,
check_interval_seconds: 300,
snmp_version: "2c",
snmp_community: "public",
snmp_port: 161
}
)
|> render_submit()
# Verify equipment was created
# Verify we stayed on the add page (no redirect)
assert html =~ "New Device"
assert html =~ "Add new device to monitor"
# Verify success message is shown
assert html =~ "Device created successfully"
# Verify device was created
device_list = Towerops.Devices.list_organization_devices(organization.id)
refute Enum.empty?(device_list)
@ -244,6 +256,48 @@ defmodule ToweropsWeb.DeviceLiveTest do
assert new_device
assert new_device.ip_address == "192.168.1.100"
assert new_device.snmp_enabled == true
# Verify form is cleared for next device
assert html =~ "name=\"device[name]\""
refute html =~ "value=\"New Router\""
end
test "allows adding multiple devices in a row", %{conn: conn, organization: organization, site: site} do
{:ok, view, _html} = live(conn, ~p"/orgs/#{organization.slug}/devices/new")
# Add first device
view
|> form("#device-form",
device: %{
name: "Router 1",
ip_address: "192.168.1.1",
site_id: site.id,
snmp_community: "public"
}
)
|> render_submit()
# Add second device (still on same view)
html =
view
|> form("#device-form",
device: %{
name: "Router 2",
ip_address: "192.168.1.2",
site_id: site.id,
snmp_community: "public"
}
)
|> render_submit()
# Verify both devices were created
device_list = Towerops.Devices.list_organization_devices(organization.id)
assert length(device_list) == 2
assert Enum.any?(device_list, &(&1.name == "Router 1"))
assert Enum.any?(device_list, &(&1.name == "Router 2"))
# Verify success message for second device
assert html =~ "Device created successfully"
end
test "validates required fields", %{conn: conn, organization: organization} do