Skip to content

Commit

Permalink
Set deployment when viewing device (#1726)
Browse files Browse the repository at this point in the history
This work adds the ability to set a device's deployment when viewing it.
If no eligible deployments are found, the UI is hidden.
  • Loading branch information
nshoes authored Jan 6, 2025
1 parent f9b7b21 commit 6a5ff1b
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 5 deletions.
13 changes: 13 additions & 0 deletions lib/nerves_hub/audit_logs/templates.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
defmodule NervesHub.AuditLogs.Templates do
alias NervesHub.Accounts.User
alias NervesHub.AuditLogs
alias NervesHub.AuditLogs.AuditLog
alias NervesHub.Deployments.Deployment
alias NervesHub.Devices.Device

require Logger

Expand Down Expand Up @@ -38,4 +42,13 @@ defmodule NervesHub.AuditLogs.Templates do
AuditLogs.audit!(device, device, description)
Logger.info("[DeviceChannel] #{description}")
end

@spec audit_device_deployment_update(User.t(), Device.t(), Deployment.t()) :: AuditLog.t()
def audit_device_deployment_update(user, device, deployment) do
AuditLogs.audit!(
user,
device,
"#{user.name} set #{device.identifier}'s deployment to #{deployment.name}"
)
end
end
22 changes: 22 additions & 0 deletions lib/nerves_hub_web/live/devices/show.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ defmodule NervesHubWeb.Live.Devices.Show do
require Logger

alias NervesHub.AuditLogs
alias NervesHub.AuditLogs.Templates
alias NervesHub.Deployments
alias NervesHub.Devices
alias NervesHub.Devices.Alarms
alias NervesHub.Devices.Connections
Expand Down Expand Up @@ -54,6 +56,7 @@ defmodule NervesHubWeb.Live.Devices.Show do
|> schedule_health_check_timer()
|> assign(:fwup_progress, nil)
|> audit_log_assigns(1)
|> assign(:eligible_deployments, Deployments.matching_deployments(device))
|> ok()
end

Expand Down Expand Up @@ -256,6 +259,23 @@ defmodule NervesHubWeb.Live.Devices.Show do
{:noreply, clear_flash(socket, String.to_existing_atom(key_str))}
end

def handle_event(
"set-deployment",
%{"deployment_id" => deployment_id},
%{assigns: %{user: user, device: device, eligible_deployments: eligible_deployments}} =
socket
) do
deployment = Enum.find(eligible_deployments, &(&1.id == String.to_integer(deployment_id)))
device = Devices.update_deployment(device, deployment)
_ = Templates.audit_device_deployment_update(user, device, deployment)

socket
|> assign(:device, device)
|> assign(:deployment, deployment)
|> put_flash(:info, "Deployment successfully updated")
|> noreply()
end

def handle_event("push-update", %{"uuid" => uuid}, socket) do
authorized!(:"device:push-update", socket.assigns.org_user)

Expand Down Expand Up @@ -362,6 +382,8 @@ defmodule NervesHubWeb.Live.Devices.Show do
socket
|> assign(:device, device)
|> assign(:deployment, nil)
|> assign(:eligible_deployments, Deployments.matching_deployments(device))
|> put_flash(:info, "Device successfully removed from the deployment")
|> noreply()
end

Expand Down
21 changes: 19 additions & 2 deletions lib/nerves_hub_web/live/devices/show.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@
<div>
<h3 class="mb-2">Deployments</h3>
<div class="display-box">
<div>
<div :if={@device.deployment_id}>
<div class="help-text mb-1">
Assigned Deployment
</div>
Expand All @@ -235,7 +235,24 @@
<span :if={is_nil(@deployment)} class="color-white-50">No Assigned Deployment</span>
</div>

<div :if={@update_information.update_available} class="mt-4">
<div :if={Enum.any?(@eligible_deployments) && is_nil(@device.deployment_id)}>
<div class="help-text mb-1">
Eligible Deployments
</div>
<form phx-submit="set-deployment">
<div class="flex-row justify-content-between">
<select name="deployment_id" class="form-control">
<option value="">Select a deployment</option>
<%= for deployment <- @eligible_deployments do %>
<option value={deployment.id}><%= deployment.name %></option>
<% end %>
</select>
<button class="btn btn-secondary ml-2">Set</button>
</div>
</form>
</div>

<div :if={@update_information.update_available && @device.deployment_id} class="mt-4">
<div class="help-text mb-1 tooltip-label help-tooltip">
<span>Update available</span>
<span class="tooltip-info"></span>
Expand Down
33 changes: 30 additions & 3 deletions test/nerves_hub_web/live/devices/show_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ defmodule NervesHubWeb.Live.Devices.ShowTest do
end

describe "clearing deployment" do
test "clears deployment", %{
test "clears deployment and eligible deployments list is refreshed", %{
conn: conn,
org: org,
product: product,
Expand All @@ -436,8 +436,12 @@ defmodule NervesHubWeb.Live.Devices.ShowTest do

conn
|> visit("/org/#{org.name}/#{product.name}/devices/#{device.identifier}")
|> click_button("Remove From Deployment")
|> assert_has("span", text: "No Assigned Deployment")
|> unwrap(fn view ->
render_change(view, "remove-from-deployment")
end)
|> assert_has("div", text: "Eligible Deployments")

refute Repo.reload(device) |> Map.get(:deployment_id)
end

test "cannot clear deployment if no deployment is set", %{
Expand All @@ -452,6 +456,29 @@ defmodule NervesHubWeb.Live.Devices.ShowTest do
end
end

describe "setting deployment" do
test "sets deployment and creates audit", %{
conn: conn,
org: org,
product: product,
device: device,
deployment: deployment
} do
assert length(AuditLogs.logs_for(device)) == 0

conn
|> visit("/org/#{org.name}/#{product.name}/devices/#{device.identifier}")
|> assert_has("div", text: "Eligible Deployment")
|> unwrap(fn view ->
render_change(view, "set-deployment", %{"deployment_id" => deployment.id})
end)
|> assert_has("div", text: "Assigned Deployment")

assert Repo.reload(device) |> Map.get(:deployment_id)
assert length(AuditLogs.logs_for(device)) == 1
end
end

def device_show_path(%{device: device, org: org, product: product}) do
~p"/org/#{org.name}/#{product.name}/devices/#{device.identifier}"
end
Expand Down

0 comments on commit 6a5ff1b

Please sign in to comment.