Skip to content
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
68 changes: 30 additions & 38 deletions lib/mast_web/live/application_live/view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ defmodule MastWeb.ApplicationLive.View do
<Layouts.app flash={@flash} active="servers" page_title={@app.name}>
<.detail_header app={@app} server={@server} release={@release} refreshing?={@refreshing?} />

<section class="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
<section class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
<.ui_stat_tile
icon="hero-cpu-chip"
label="Memory"
Expand Down Expand Up @@ -103,10 +103,9 @@ defmodule MastWeb.ApplicationLive.View do
defp system_snapshot(assigns) do
~H"""
<section class="mt-6 rounded-[var(--radius-lg)] bg-[var(--mast-bg-card)] border border-[var(--mast-border)] p-5">
<header class="flex items-center mb-4">
<header class="flex flex-wrap items-center gap-2 mb-4">
<h3 class="text-[15px] font-semibold text-[var(--mast-font-primary)]">System snapshot</h3>
<span class="flex-1" />
<.ui_badge variant="online" size="sm">live</.ui_badge>
<.ui_badge variant="online" size="sm" class="ml-auto">live</.ui_badge>
</header>

<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
Expand Down Expand Up @@ -152,9 +151,11 @@ defmodule MastWeb.ApplicationLive.View do

defp snapshot_row(assigns) do
~H"""
<div class="flex items-center gap-3">
<span class="text-[13px] text-[var(--mast-font-secondary)] w-44 shrink-0">{@label}</span>
<div class="flex-1">{render_slot(@inner_block)}</div>
<div class="flex flex-col sm:flex-row sm:items-center gap-1 sm:gap-3">
<span class="text-[13px] text-[var(--mast-font-secondary)] sm:w-44 shrink-0">
{@label}
</span>
<div class="flex-1 min-w-0">{render_slot(@inner_block)}</div>
</div>
"""
end
Expand Down Expand Up @@ -186,7 +187,7 @@ defmodule MastWeb.ApplicationLive.View do
style={"width: #{pct_of(Map.get(@categories, key), @total)}%; background-color: #{color};"}
/>
</div>
<ul class="grid grid-cols-2 gap-x-4 gap-y-1 text-[12px]">
<ul class="grid grid-cols-1 sm:grid-cols-2 gap-x-4 gap-y-1 text-[12px]">
<li :for={{key, label, color} <- @cats} class="flex items-center gap-2">
<span class="size-2 rounded-sm shrink-0" style={"background-color: #{color};"} />
<span class="text-[var(--mast-font-secondary)]">{label}</span>
Expand Down Expand Up @@ -279,12 +280,14 @@ defmodule MastWeb.ApplicationLive.View do
~H"""
<section class="mt-6 grid grid-cols-1 lg:grid-cols-2 gap-4">
<.proc_table
id="proc-top-memory"
title="Top by memory"
rows={@memory}
value_label="Memory"
value_fn={&format_bytes(&1[:memory])}
/>
<.proc_table
id="proc-top-msgq"
title="Top by message queue"
rows={@msgq}
value_label="Queue"
Expand All @@ -294,44 +297,33 @@ defmodule MastWeb.ApplicationLive.View do
"""
end

attr :id, :string, required: true
attr :title, :string, required: true
attr :rows, :list, required: true
attr :value_label, :string, required: true
attr :value_fn, :any, required: true

defp proc_table(assigns) do
~H"""
<div class="rounded-[var(--radius-lg)] bg-[var(--mast-bg-card)] border border-[var(--mast-border)] overflow-hidden">
<header class="flex items-center h-12 px-4 border-b border-[var(--mast-border)]">
<.ui_table id={@id} rows={@rows} size="sm" empty="No processes reported.">
<:action_bar>
<h3 class="text-[14px] font-semibold text-[var(--mast-font-primary)]">{@title}</h3>
</header>
<div :if={@rows == []} class="px-4 py-6 text-[13px] text-[var(--mast-font-tertiary)]">
No processes reported.
</div>
<table :if={@rows != []} class="w-full text-[12px]">
<thead>
<tr class="text-left text-[var(--mast-font-tertiary)]">
<th class="font-medium px-4 py-2">Process</th>
<th class="font-medium px-4 py-2 text-right">{@value_label}</th>
<th class="font-medium px-4 py-2 text-right">Reductions</th>
</tr>
</thead>
<tbody>
<tr
:for={row <- @rows}
class="border-t border-[var(--mast-border)]"
>
<td class="px-4 py-2 font-mono truncate max-w-[180px]">
{row[:name] || row[:pid]}
</td>
<td class="px-4 py-2 text-right font-mono tabular-nums">{@value_fn.(row)}</td>
<td class="px-4 py-2 text-right font-mono tabular-nums text-[var(--mast-font-secondary)]">
{format_int(row[:reductions])}
</td>
</tr>
</tbody>
</table>
</div>
</:action_bar>
<:col :let={row} label="Process" class="font-mono truncate max-w-[180px]">
{row[:name] || row[:pid]}
</:col>
<:col :let={row} label={@value_label} align="right" class="font-mono tabular-nums">
{@value_fn.(row)}
</:col>
<:col
:let={row}
label="Reductions"
align="right"
class="font-mono tabular-nums text-[var(--mast-font-secondary)]"
>
{format_int(row[:reductions])}
</:col>
</.ui_table>
"""
end

Expand Down
4 changes: 2 additions & 2 deletions lib/mast_web/live/dashboard_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ defmodule MastWeb.DashboardLive do
</:actions>
</.ui_page_header>

<section class="grid grid-cols-2 lg:grid-cols-4 gap-3 mb-6">
<section class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 mb-6">
<.ui_stat label="Total Servers" value={@stats.total} />
<.ui_stat label="Online" value={@stats.online} tone="online" />
<.ui_stat
Expand Down Expand Up @@ -233,7 +233,7 @@ defmodule MastWeb.DashboardLive do
>
<.input field={@form[:name]} label="Name" placeholder="web-1" required />
<.input field={@form[:host]} label="Host" placeholder="10.0.0.7 or fqdn" required />
<div class="grid grid-cols-2 gap-3">
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
<.input field={@form[:user]} label="SSH user" placeholder="ubuntu" />
<.input field={@form[:port]} type="number" label="Port" placeholder="22" />
</div>
Expand Down
2 changes: 1 addition & 1 deletion lib/mast_web/live/server_live/overview_tab.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ defmodule MastWeb.ServerLive.OverviewTab do

def render(assigns) do
~H"""
<section class="grid grid-cols-2 lg:grid-cols-4 gap-3 mb-5">
<section class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 mb-5">
<.ui_stat
label="CPU Usage"
value={format_pct(@server.cpu)}
Expand Down
26 changes: 7 additions & 19 deletions lib/mast_web/live/server_live/settings_tab.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,13 @@ defmodule MastWeb.ServerLive.SettingsTab do
def render(assigns) do
~H"""
<div class="space-y-5">
<.ui_card>
<:title>Connection</:title>
<:subtitle>SSH details for this host</:subtitle>

<dl class="grid grid-cols-2 gap-y-3 text-sm">
<dt class="text-[var(--mast-font-secondary)]">Host</dt>
<dd class="font-mono text-[var(--mast-font-primary)]">{@server.host}</dd>
<dt class="text-[var(--mast-font-secondary)]">User</dt>
<dd class="font-mono text-[var(--mast-font-primary)]">{@server.user}</dd>
<dt class="text-[var(--mast-font-secondary)]">Port</dt>
<dd class="font-mono text-[var(--mast-font-primary)]">{@server.port}</dd>
<dt class="text-[var(--mast-font-secondary)]">OS</dt>
<dd class="font-mono text-[var(--mast-font-primary)]">{@server.os_id || "—"}</dd>
<dt class="text-[var(--mast-font-secondary)]">Package manager</dt>
<dd class="font-mono text-[var(--mast-font-primary)]">
{@server.package_manager || "—"}
</dd>
</dl>
</.ui_card>
<.ui_kv_table title="Connection">
<:row label="Host">{@server.host}</:row>
<:row label="User">{@server.user}</:row>
<:row label="Port">{@server.port}</:row>
<:row label="OS">{@server.os_id || "—"}</:row>
<:row label="Package manager">{@server.package_manager || "—"}</:row>
</.ui_kv_table>

<div class="rounded-[var(--radius-box)] border border-[var(--mast-status-offline)] bg-[var(--mast-bg-card)] p-6">
<div class="flex items-center justify-between gap-4 flex-wrap">
Expand Down
64 changes: 35 additions & 29 deletions lib/mast_web/live/server_live/updates_tab.ex
Original file line number Diff line number Diff line change
Expand Up @@ -35,40 +35,46 @@ defmodule MastWeb.ServerLive.UpdatesTab do
|> assign(:state, state)

~H"""
<.ui_card padded={false}>
<:header>
<div class="flex items-center justify-between gap-3 w-full">
<div>
<h2 class="text-base font-semibold text-[var(--mast-font-primary)]">Available Updates</h2>
<p class="text-xs text-[var(--mast-font-secondary)] mt-1">
<.scan_status_text server={@server} scanning?={@scanning?} scan_error={@scan_error} />
</p>
</div>
<.ui_badge :if={@updates != []} variant="warning">
{length(@updates)} packages
</.ui_badge>
<div class="space-y-6">
<div class="flex items-start gap-3">
<div class="flex-1 min-w-0">
<h2 class="text-lg font-bold text-[var(--mast-font-primary)] leading-tight">
Available Updates
</h2>
<p class="text-[13px] text-[var(--mast-font-secondary)] mt-0.5">
<.scan_status_text server={@server} scanning?={@scanning?} scan_error={@scan_error} />
</p>
</div>
</:header>
<.ui_badge :if={@updates != []} variant="warning" class="shrink-0 mt-1">
{length(@updates)} packages
</.ui_badge>
</div>

<%= case @state do %>
<% :scanning -> %>
<.ui_empty
icon="hero-magnifying-glass"
title="Scanning…"
body="Running apt list --upgradable on the host."
/>
<.ui_card padded={false}>
<.ui_empty
icon="hero-magnifying-glass"
title="Scanning…"
body="Running apt list --upgradable on the host."
/>
</.ui_card>
<% :never_scanned -> %>
<.ui_empty
icon="hero-magnifying-glass"
title="Not scanned yet"
body="Click Scan Updates above to check the host for available packages."
/>
<.ui_card padded={false}>
<.ui_empty
icon="hero-magnifying-glass"
title="Not scanned yet"
body="Click Scan Updates above to check the host for available packages."
/>
</.ui_card>
<% :clean -> %>
<.ui_empty
icon="hero-check-circle"
title="All up to date"
body="No package updates are available right now."
/>
<.ui_card padded={false}>
<.ui_empty
icon="hero-check-circle"
title="All up to date"
body="No package updates are available right now."
/>
</.ui_card>
<% :has_updates -> %>
<form id="updates-filter" phx-change="filter-updates" class="contents">
<.ui_table id="updates-table" rows={@page_rows} size="sm">
Expand Down Expand Up @@ -123,7 +129,7 @@ defmodule MastWeb.ServerLive.UpdatesTab do
</.ui_table>
</form>
<% end %>
</.ui_card>
</div>
"""
end

Expand Down
104 changes: 47 additions & 57 deletions lib/mast_web/live/settings_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -192,68 +192,58 @@ defmodule MastWeb.SettingsLive do
</.form>
</div>

<div class="bg-[var(--mast-bg-card)] border border-[var(--mast-border)] rounded-[var(--radius-box)] overflow-hidden">
<%= if @keys == [] do %>
<%= if @keys == [] do %>
<div class="bg-[var(--mast-bg-card)] border border-[var(--mast-border)] rounded-[var(--radius-box)] overflow-hidden">
<.ui_empty
icon="hero-key"
title="No SSH keys yet"
body="Add an Ed25519 or RSA private key to connect to your servers."
/>
<% else %>
<div class="overflow-x-auto">
<table class="w-full table table-zebra table-sm">
<thead class="bg-[var(--mast-bg-secondary)] text-[var(--mast-font-secondary)]">
<tr>
<th class="text-left text-xs font-semibold uppercase tracking-wider">Name</th>
<th class="text-left text-xs font-semibold uppercase tracking-wider">Type</th>
<th class="text-left text-xs font-semibold uppercase tracking-wider">
Fingerprint
</th>
<th class="text-left text-xs font-semibold uppercase tracking-wider">Servers</th>
<th class="text-left text-xs font-semibold uppercase tracking-wider">Created</th>
<th></th>
</tr>
</thead>
<tbody>
<tr :for={k <- @keys} class="hover:bg-[var(--mast-bg-card-hover)]">
<td class="font-mono font-medium text-[var(--mast-font-primary)]">
<span class="inline-flex items-center gap-2">
<span class="hero-key size-4 text-[var(--mast-font-tertiary)]" />
{k.name}
</span>
</td>
<td>
<.ui_badge variant={algo_variant(k.algorithm)} dot={false}>
{k.algorithm || "—"}
</.ui_badge>
</td>
<td class="font-mono text-xs text-[var(--mast-font-secondary)]">
{short_fp(k.fingerprint)}
</td>
<td class="font-mono text-[var(--mast-font-primary)] tabular-nums">
{server_count_label(@server_counts, k.id)}
</td>
<td class="text-xs text-[var(--mast-font-secondary)]">
{format_date(k.inserted_at)}
</td>
<td class="text-right">
<button
type="button"
phx-click="delete-key"
phx-value-id={k.id}
data-confirm={"Delete key #{k.name}? Servers using it will lose their key reference."}
class="text-[var(--mast-font-tertiary)] hover:text-[var(--mast-status-offline)] p-1"
aria-label="Delete key"
>
<span class="hero-trash size-4" />
</button>
</td>
</tr>
</tbody>
</table>
</div>
<% end %>
</div>
</div>
<% else %>
<.ui_table id="ssh-keys" rows={@keys} size="sm">
<:col :let={k} label="Name">
<span class="inline-flex items-center gap-2 font-mono font-medium text-[var(--mast-font-primary)]">
<span class="hero-key size-4 text-[var(--mast-font-tertiary)]" />
{k.name}
</span>
</:col>
<:col :let={k} label="Type">
<.ui_badge variant={algo_variant(k.algorithm)} dot={false}>
{k.algorithm || "—"}
</.ui_badge>
</:col>
<:col
:let={k}
label="Fingerprint"
class="font-mono text-xs text-[var(--mast-font-secondary)]"
>
{short_fp(k.fingerprint)}
</:col>
<:col
:let={k}
label="Servers"
class="font-mono text-[var(--mast-font-primary)] tabular-nums"
>
{server_count_label(@server_counts, k.id)}
</:col>
<:col :let={k} label="Created" class="text-xs text-[var(--mast-font-secondary)]">
{format_date(k.inserted_at)}
</:col>
<:col :let={k} align="right">
<button
type="button"
phx-click="delete-key"
phx-value-id={k.id}
data-confirm={"Delete key #{k.name}? Servers using it will lose their key reference."}
class="text-[var(--mast-font-tertiary)] hover:text-[var(--mast-status-offline)] p-1"
aria-label="Delete key"
>
<span class="hero-trash size-4" />
</button>
</:col>
</.ui_table>
<% end %>

<div class="flex items-start gap-3 px-4 py-3 bg-[var(--mast-bg-secondary)] rounded-[var(--radius-field)] text-[13px] text-[var(--mast-font-secondary)]">
<span class="hero-information-circle size-4 shrink-0 mt-0.5" />
Expand Down
Loading