Skip to content

Commit

Permalink
Start new deployment-group workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
nshoes committed Dec 20, 2024
1 parent dc97780 commit bac910f
Show file tree
Hide file tree
Showing 4 changed files with 542 additions and 60 deletions.
4 changes: 0 additions & 4 deletions lib/nerves_hub/devices/device.ex
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,6 @@ defmodule NervesHub.Devices.Device do
field(:connecting_code, :string)
field(:connection_metadata, :map, default: %{})

field(:deployment_conflict, Ecto.Enum,
values: [:bad_architecture, :bad_platform, :bad_architecture_and_platform]
)

timestamps()

# Deprecated fields, replaced with device_connections table.
Expand Down
226 changes: 224 additions & 2 deletions lib/nerves_hub_web/live/deployment_groups/new.ex
Original file line number Diff line number Diff line change
@@ -1,15 +1,76 @@
defmodule NervesHubWeb.Live.DeploymentGroup.New do
use NervesHubWeb, :updated_live_view

import NervesHubWeb.LayoutView

alias NervesHub.AuditLogs
alias NervesHub.Devices
alias NervesHub.ManagedDeployments
alias NervesHub.ManagedDeployments.DeploymentGroup
alias NervesHub.Tracker
alias NervesHub.Firmwares
alias NervesHub.Firmwares.Firmware

alias NervesHubWeb.LayoutView.DateTimeFormat

# @default_page 1
# @default_page_size 25

@default_filters %{
connection: "",
connection_type: "",
firmware_version: "",
platform: "",
healthy: "",
device_id: "",
tag: "",
updates: "",
has_no_tags: false,
alarm_status: "",
alarm: "",
metrics_key: "",
metrics_operator: "gt",
metrics_value: ""
}

@default_page 1
@default_page_size 25

@default_pagination %{
page_number: @default_page,
page_size: @default_page_size,
page_sizes: [25, 50, 100],
total_pages: 0
}

@pagination_types %{
page_number: :integer,
page_size: :integer,
page_sizes: {:array, :integer},
total_pages: :integer
}

@filter_types %{
connection: :string,
connection_type: :string,
firmware_version: :string,
platform: :string,
healthy: :string,
device_id: :string,
tag: :string,
updates: :string,
has_no_tags: :boolean,
alarm_status: :string,
alarm: :string,
metrics_key: :string,
metrics_operator: :string,
metrics_value: :string
}

@impl Phoenix.LiveView
def mount(_params, _session, %{assigns: %{org: org, product: product}} = socket) do
firmware = Firmwares.get_firmwares_by_product(socket.assigns.product.id)
firmware = Firmwares.get_firmwares_by_product(product.id)
firmware_versions = Firmwares.get_firmware_versions_by_product(product.id)

if Enum.empty?(firmware) do
socket
Expand All @@ -26,14 +87,35 @@ defmodule NervesHubWeb.Live.DeploymentGroup.New do
|> Enum.uniq()

socket
|> page_title("New Deployment - #{socket.assigns.product.name}")
|> page_title("New Deployment Group - #{socket.assigns.product.name}")
|> assign(:platforms, platforms)
|> assign(:platform, nil)
|> assign(:form, to_form(Ecto.Changeset.change(%DeploymentGroup{})))
|> assign(:paginate_opts, @default_filters)
|> assign(:total_entries, 0)
|> assign(:selected_devices, [])
|> assign(:current_filters, @default_filters)
|> assign(:firmware_versions, firmware_versions)
|> ok()
end
end

def handle_params(unsigned_params, _uri, socket) do
filters = Map.merge(@default_filters, filter_changes(unsigned_params))
changes = pagination_changes(unsigned_params)
pagination_opts = Map.merge(@default_pagination, changes)

socket
|> assign(:current_sort, Map.get(unsigned_params, "sort", "identifier"))
|> assign(:sort_direction, Map.get(unsigned_params, "sort_direction", "asc"))
|> assign(:current_filters, filters)
|> assign(:paginate_opts, pagination_opts)
|> assign(:currently_filtering, filters != @default_filters)
|> assign(:params, unsigned_params)
|> assign_display_devices()
|> noreply()
end

@impl Phoenix.LiveView
def handle_event("select-platform", %{"deployment_group" => %{"platform" => platform}}, socket) do
authorized!(:"deployment_group:create", socket.assigns.org_user)
Expand Down Expand Up @@ -159,4 +241,144 @@ defmodule NervesHubWeb.Live.DeploymentGroup.New do
|> String.split(",")
|> Enum.map(&String.trim/1)
end

# ___________________________________________________

defp last_seen_at(connections) do
case connections do
[latest_connection | _] ->
last_seen_formatted(latest_connection)

_ ->
""
end
end

defp last_seen_at_status(connections) do
case connections do
[] ->
"Not seen yet"

[latest_connection | _] ->
"Last seen #{last_seen_formatted(latest_connection)}"
end
end

defp last_seen_formatted(connection) do
connection
|> Map.get(:last_seen_at)
|> DateTimeFormat.from_now()
end

defp devices_table_header(title, value, current_sort, sort_direction)
when value == current_sort do
caret_class = if sort_direction == "asc", do: "up", else: "down"

assigns = %{value: value, title: title, caret_class: caret_class}

~H"""
<th phx-click="sort" phx-value-sort={@value} class="pointer sort-selected">
<%= @title %><i class={"icon-caret icon-caret-#{@caret_class}"} />
</th>
"""
end

defp devices_table_header(title, value, _current_sort, _sort_direction) do
assigns = %{value: value, title: title}

~H"""
<th phx-click="sort" phx-value-sort={@value} class="pointer">
<%= @title %>
</th>
"""
end

defp firmware_update_status(device) do
cond do
Devices.device_in_penalty_box?(device) ->
"firmware-penalty-box"

device.updates_enabled == false ->
"firmware-disabled"

true ->
"firmware-enabled"
end
end

defp firmware_update_title(device) do
cond do
Devices.device_in_penalty_box?(device) ->
"Automatic Penalty Box"

device.updates_enabled == false ->
"Firmware Disabled"

true ->
"Firmware Enabled"
end
end

defp selected?(filters, field, value) do
if filters[field] == value do
[selected: true]
else
[]
end
end

defp assign_display_devices(
%{assigns: %{product: product, paginate_opts: paginate_opts}} = socket
) do
opts = %{
pagination: %{page: paginate_opts.page_number, page_size: paginate_opts.page_size},
sort:
{String.to_existing_atom(socket.assigns.sort_direction),
String.to_atom(socket.assigns.current_sort)},
filters: socket.assigns.current_filters
}

page = Devices.filter(product.id, opts)

statuses =
Enum.into(page.entries, %{}, fn device ->
socket.endpoint.subscribe("device:#{device.identifier}:internal")

{device.identifier, Tracker.connection_status(device)}
end)

socket
|> assign(:device_statuses, statuses)
|> assign_display_devices(page)
end

defp assign_display_devices(%{assigns: %{paginate_opts: paginate_opts}} = socket, page) do
paginate_opts =
paginate_opts
|> Map.put(:page_number, page.current_page)
|> Map.put(:page_size, page.page_size)
|> Map.put(:total_pages, page.total_pages)

socket
|> assign(:devices, page.entries)
|> assign(:total_entries, page.total_count)
|> assign(:paginate_opts, paginate_opts)
end

defp filter_changes(params) do
Ecto.Changeset.cast({@default_filters, @filter_types}, params, Map.keys(@default_filters),
empty_values: []
).changes
end

defp pagination_changes(params) do
Ecto.Changeset.cast(
{@default_pagination, @pagination_types},
params,
Map.keys(@default_pagination)
).changes
end

# defp target_selected?(%{name: name}, value) when name == value, do: [selected: true]
# defp target_selected?(_, _), do: []
end
Loading

0 comments on commit bac910f

Please sign in to comment.