Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add device count and estimated device count for Deployment views #1517

Merged
merged 1 commit into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions assets/css/_layout.scss
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,21 @@ html {
}
}

.x5-grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
grid-column-gap: 2rem;
grid-row-gap: 2rem;

@media (max-width: 860px) {
grid-template-columns: 1fr 1fr;
}

@media (max-width: 600px) {
grid-template-columns: 1fr;
}
}

.x2-grid {
display: grid;
grid-template-columns: 1fr 1fr;
Expand Down Expand Up @@ -411,5 +426,4 @@ html {
.gr-2 {
grid-row: 2;
}
}

}
38 changes: 38 additions & 0 deletions lib/nerves_hub/deployments.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,24 @@ defmodule NervesHub.Deployments do
|> Repo.all()
end

@spec get_deployment_device_counts_by_product(integer()) :: %{integer() => integer()}
def get_deployment_device_counts_by_product(product_id) do
Device
|> select([d], {d.deployment_id, count(d.id)})
|> where([d], d.product_id == ^product_id)
|> group_by([d], d.id)
|> Repo.all()
|> Map.new()
end

@spec get_deployment_device_count(integer()) :: %{integer() => integer()}
def get_deployment_device_count(deployment_id) do
Device
|> select([d], count(d.id))
|> where([d], d.deployment_id == ^deployment_id)
|> Repo.one()
end

@spec get_deployments_by_firmware(integer()) :: [Deployment.t()]
def get_deployments_by_firmware(firmware_id) do
from(d in Deployment, where: d.firmware_id == ^firmware_id)
Expand Down Expand Up @@ -328,6 +346,11 @@ defmodule NervesHub.Deployments do
:ok
end

@spec change_deployment(Deployment.t(), map()) :: Changeset.t()
def change_deployment(deployment, params) do
Deployment.changeset(deployment, params)
end

@spec create_deployment(map) :: {:ok, Deployment.t()} | {:error, Changeset.t()}
def create_deployment(params) do
changeset = Deployment.creation_changeset(%Deployment{}, params)
Expand Down Expand Up @@ -405,6 +428,21 @@ defmodule NervesHub.Deployments do
)
end

@doc """
Find all potential devices for a deployment

Based on the product, firmware platform, firmware architecture, and device tags
"""
def estimate_devices_matched_by_conditions(product_id, platform, conditions) do
Device
|> where([dev], dev.product_id == ^product_id)
|> where([dev], fragment("d0.firmware_metadata ->> 'platform'") == ^platform)
|> where([dev], fragment("?::jsonb->'tags' <@ to_jsonb(?::text[])", ^conditions, dev.tags))
|> Repo.all()
|> Enum.filter(&version_match?(&1, %{conditions: conditions}))
|> Enum.count()
end

@doc """
Check that a device version matches for a deployment's conditions

Expand Down
35 changes: 34 additions & 1 deletion lib/nerves_hub_web/live/deployments/edit.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,56 @@ defmodule NervesHubWeb.Live.Deployments.Edit do
%{"name" => name} = params
%{product: product} = socket.assigns

deployment = Deployments.get_by_product_and_name!(product, name)
deployment =
Deployments.get_by_product_and_name!(product, name) |> NervesHub.Repo.preload(:firmware)

current_device_count = Deployments.get_deployment_device_count(deployment.id)

archives = Archives.all_by_product(deployment.product)
firmwares = Firmwares.get_firmwares_for_deployment(deployment)

changeset = Deployment.changeset(deployment, %{}) |> tags_to_string()

estimate_count =
Deployments.estimate_devices_matched_by_conditions(
deployment.product_id,
deployment.firmware.platform,
deployment.conditions
)

socket
|> assign(:archives, archives)
|> assign(:deployment, deployment)
|> assign(:current_device_count, current_device_count)
|> assign(:estimate_count, estimate_count)
|> assign(:firmware, deployment.firmware)
|> assign(:firmwares, firmwares)
|> assign(:form, to_form(changeset))
|> ok()
end

@impl Phoenix.LiveView
def handle_event("recalculate", %{"deployment" => params}, socket) do
params = inject_conditions_map(params)

try do
count =
Deployments.estimate_devices_matched_by_conditions(
socket.assigns.deployment.product_id,
socket.assigns.deployment.firmware.platform,
params["conditions"]
)

changeset = Deployments.change_deployment(socket.assigns.deployment, params)

{:noreply, assign(socket, estimate_count: count, form: to_form(tags_to_string(changeset)))}
rescue
_ ->
# Ignore version parsing errors
{:noreply, socket}
end
end

def handle_event("update-deployment", %{"deployment" => params}, socket) do
%{org_user: org_user, org: org, product: product, user: user, deployment: deployment} =
socket.assigns
Expand Down
13 changes: 9 additions & 4 deletions lib/nerves_hub_web/live/deployments/edit.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<h1>Edit Deployment</h1>

<h5 class="mb-2">Firmware version details</h5>
<div class="x4-grid">
<div class="x5-grid">
<div>
<div class="help-text mb-1">Product</div>
<p><%= @product.name %></p>
Expand All @@ -26,11 +26,15 @@
<div class="help-text mb-1">Architecture</div>
<p><%= @firmware.architecture %></p>
</div>
<div>
<div class="help-text mb-1">Device count</div>
<p><%= @current_device_count %></p>
</div>
</div>

<div class="divider"></div>

<.form :let={f} for={@form} phx-submit="update-deployment">
<.form :let={f} for={@form} phx-change="recalculate" phx-submit="update-deployment">
<%= hidden_input(f, :firmware_id, value: @firmware.id) %>

<div class="form-group">
Expand Down Expand Up @@ -64,6 +68,7 @@
<h3 class="mb-2">Conditions</h3>

<p>Changing any conditions will reset any attached devices.</p>
<p>Estimated affected devices: <%= @estimate_count %></p>

<div class="form-group">
<div class="help-text tooltip-label help-tooltip">
Expand All @@ -78,7 +83,7 @@
id: "tags_input",
value:
@form.source
|> Ecto.Changeset.get_change(:conditions, %{})
|> Ecto.Changeset.get_field(:conditions, %{})
|> Map.get("tags", "")
) %>
<div class="has-error"><%= error_tag(f, :tags) %></div>
Expand All @@ -97,7 +102,7 @@
id: "version_requirement",
value:
@form.source
|> Ecto.Changeset.get_change(:conditions, %{})
|> Ecto.Changeset.get_field(:conditions, %{})
|> Map.get("version", "")
) %>
<div class="has-error"><%= error_tag(f, :version) %></div>
Expand Down
2 changes: 2 additions & 0 deletions lib/nerves_hub_web/live/deployments/index.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ defmodule NervesHubWeb.Live.Deployments.Index do
@impl Phoenix.LiveView
def mount(_params, _session, %{assigns: %{product: product}} = socket) do
deployments = Deployments.get_deployments_by_product(product.id)
counts = Deployments.get_deployment_device_counts_by_product(product.id)

deployments =
deployments
Expand All @@ -19,6 +20,7 @@ defmodule NervesHubWeb.Live.Deployments.Index do
socket
|> page_title("Deployments - #{product.name}")
|> assign(:deployments, deployments)
|> assign(:counts, counts)
|> ok()
end

Expand Down
7 changes: 7 additions & 0 deletions lib/nerves_hub_web/live/deployments/index.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<tr>
<th>Name</th>
<th>State</th>
<th>Devices</th>
<th>Firmware version</th>
<th>Distributed to</th>
<th>Version requirement</th>
Expand All @@ -44,6 +45,12 @@
<%= if deployment.is_active, do: "On", else: "Off" %>
</div>
</td>
<td>
<div class="mobile-label help-text">Devices</div>
<div>
<%= @counts[deployment.id] %>
</div>
</td>
<td>
<div class="mobile-label help-text">Firmware version</div>
<div>
Expand Down
2 changes: 2 additions & 0 deletions lib/nerves_hub_web/live/deployments/show.ex
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ defmodule NervesHubWeb.Live.Deployments.Show do
|> Map.put(:anchor, "latest-activity")

inflight_updates = Devices.inflight_updates_for(deployment)
current_device_count = Deployments.get_deployment_device_count(deployment.id)

socket
|> page_title("Deployment - #{deployment.name} - #{product.name}")
|> assign(:deployment, deployment)
|> assign(:audit_logs, logs)
|> assign(:inflight_updates, inflight_updates)
|> assign(:firmware, deployment.firmware)
|> assign(:current_device_count, current_device_count)
|> schedule_inflight_updates_updater()
|> ok()
end
Expand Down
4 changes: 4 additions & 0 deletions lib/nerves_hub_web/live/deployments/show.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@
<div class="help-text mb-1">Version requirement</div>
<p><%= version(@deployment) %></p>
</div>
<div>
<div class="help-text mb-1">Current device count</div>
<p><%= @current_device_count %></p>
</div>
<div class="row">
<div class="col-lg-6 mb-1">
<div class="help-text mb-1 tooltip-label">
Expand Down
Loading