Changed the default filter from 'all' to 'active' and reordered tabs so Active Alerts appears first (leftmost) in the tab bar
155 lines
6.2 KiB
Text
155 lines
6.2 KiB
Text
<Layouts.authenticated
|
|
flash={@flash}
|
|
current_scope={@current_scope}
|
|
current_organization={@current_organization}
|
|
active_page="alerts"
|
|
>
|
|
<.header>
|
|
Alerts
|
|
<:subtitle>Monitor and acknowledge system alerts</:subtitle>
|
|
</.header>
|
|
|
|
<div class="mb-6">
|
|
<div class="inline-flex rounded-lg border border-zinc-200 dark:border-zinc-800">
|
|
<.link
|
|
patch={~p"/orgs/#{@current_organization.slug}/alerts"}
|
|
class={[
|
|
"px-4 py-2 text-sm font-medium rounded-l-lg",
|
|
@filter == "active" &&
|
|
"bg-blue-600 text-white dark:bg-blue-500",
|
|
@filter != "active" &&
|
|
"bg-white text-zinc-700 hover:bg-zinc-50 dark:bg-zinc-900 dark:text-zinc-300 dark:hover:bg-zinc-800"
|
|
]}
|
|
>
|
|
Active Alerts
|
|
</.link>
|
|
<.link
|
|
patch={~p"/orgs/#{@current_organization.slug}/alerts?filter=all"}
|
|
class={[
|
|
"px-4 py-2 text-sm font-medium rounded-r-lg border-l border-zinc-200 dark:border-zinc-800",
|
|
@filter == "all" &&
|
|
"bg-blue-600 text-white dark:bg-blue-500",
|
|
@filter != "all" &&
|
|
"bg-white text-zinc-700 hover:bg-zinc-50 dark:bg-zinc-900 dark:text-zinc-300 dark:hover:bg-zinc-800"
|
|
]}
|
|
>
|
|
All Alerts
|
|
</.link>
|
|
</div>
|
|
</div>
|
|
|
|
<%= if Enum.empty?(@alerts) do %>
|
|
<div class="text-center py-16">
|
|
<.icon name="hero-bell-slash" class="mx-auto h-12 w-12 text-zinc-400 dark:text-zinc-600" />
|
|
<h3 class="mt-4 text-lg font-semibold text-zinc-900 dark:text-zinc-100">No alerts</h3>
|
|
<p class="mt-2 text-sm text-zinc-600 dark:text-zinc-400">
|
|
<%= if @filter == "active" do %>
|
|
There are no active alerts for this organization.
|
|
<% else %>
|
|
No alerts have been triggered yet.
|
|
<% end %>
|
|
</p>
|
|
</div>
|
|
<% else %>
|
|
<div class="space-y-4">
|
|
<%= for alert <- @alerts do %>
|
|
<div class={[
|
|
"rounded-lg border p-6 shadow-sm",
|
|
alert.resolved_at && "opacity-60",
|
|
alert.alert_type == :device_down && is_nil(alert.resolved_at) &&
|
|
"border-l-4 border-red-500 bg-red-50 dark:bg-red-950 dark:border-red-700",
|
|
(alert.alert_type != :device_down || alert.resolved_at) &&
|
|
"border-zinc-200 bg-white dark:border-zinc-800 dark:bg-zinc-900"
|
|
]}>
|
|
<div class="flex items-start justify-between">
|
|
<div class="flex-1">
|
|
<div class="flex items-center gap-3 flex-wrap">
|
|
<span class={[
|
|
"inline-flex items-center gap-1.5 rounded-full px-3 py-1 text-sm font-medium",
|
|
alert.alert_type == :device_down &&
|
|
"bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200",
|
|
alert.alert_type == :device_up &&
|
|
"bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200"
|
|
]}>
|
|
<%= case alert.alert_type do %>
|
|
<% :device_down -> %>
|
|
<.icon name="hero-exclamation-triangle" class="h-4 w-4" /> Device Down
|
|
<% :device_up -> %>
|
|
<.icon name="hero-check-circle" class="h-4 w-4" /> Device Recovered
|
|
<% end %>
|
|
</span>
|
|
|
|
<%= if alert.resolved_at do %>
|
|
<span class="inline-flex items-center rounded-full bg-zinc-100 px-2.5 py-0.5 text-xs font-medium text-zinc-800 dark:bg-zinc-800 dark:text-zinc-200">
|
|
Resolved
|
|
</span>
|
|
<% end %>
|
|
|
|
<%= if alert.acknowledged_at do %>
|
|
<span class="inline-flex items-center rounded-full bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800 dark:bg-blue-900 dark:text-blue-200">
|
|
Acknowledged
|
|
</span>
|
|
<% end %>
|
|
</div>
|
|
|
|
<h3 class="mt-3 font-semibold text-zinc-900 dark:text-zinc-100">
|
|
<.link
|
|
navigate={~p"/orgs/#{@current_organization.slug}/devices/#{alert.device.id}"}
|
|
class="text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
|
|
>
|
|
{alert.device.name}
|
|
</.link>
|
|
</h3>
|
|
|
|
<p class="mt-1 text-sm text-zinc-700 dark:text-zinc-300">{alert.message}</p>
|
|
|
|
<div class="mt-3 space-y-1 text-xs text-zinc-600 dark:text-zinc-400">
|
|
<div>
|
|
<strong class="font-medium">Triggered:</strong>
|
|
{Calendar.strftime(alert.triggered_at, "%Y-%m-%d %H:%M:%S UTC")}
|
|
</div>
|
|
|
|
<%= if alert.acknowledged_at do %>
|
|
<div>
|
|
<strong class="font-medium">Acknowledged:</strong>
|
|
{Calendar.strftime(alert.acknowledged_at, "%Y-%m-%d %H:%M:%S UTC")}
|
|
<%= if alert.acknowledged_by do %>
|
|
by {alert.acknowledged_by.email}
|
|
<% end %>
|
|
</div>
|
|
<% end %>
|
|
|
|
<%= if alert.resolved_at do %>
|
|
<div>
|
|
<strong class="font-medium">Resolved:</strong>
|
|
{Calendar.strftime(alert.resolved_at, "%Y-%m-%d %H:%M:%S UTC")}
|
|
</div>
|
|
<% end %>
|
|
|
|
<div>
|
|
<strong class="font-medium">Site:</strong>
|
|
<.link
|
|
navigate={
|
|
~p"/orgs/#{@current_organization.slug}/sites/#{alert.device.site.id}"
|
|
}
|
|
class="text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
|
|
>
|
|
{alert.device.site.name}
|
|
</.link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ml-4">
|
|
<%= if alert.alert_type == :device_down && is_nil(alert.acknowledged_at) && is_nil(alert.resolved_at) do %>
|
|
<.button phx-click="acknowledge" phx-value-id={alert.id} variant="primary">
|
|
<.icon name="hero-check" class="h-4 w-4" /> Acknowledge
|
|
</.button>
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
<% end %>
|
|
</Layouts.authenticated>
|