140 lines
4.8 KiB
Text
140 lines
4.8 KiB
Text
<.header>
|
|
Alerts
|
|
<:subtitle>Monitor and acknowledge system alerts</:subtitle>
|
|
</.header>
|
|
|
|
<div class="mt-6">
|
|
<div class="tabs tabs-boxed">
|
|
<.link
|
|
patch={~p"/orgs/#{@current_organization.slug}/alerts"}
|
|
class={["tab", @filter == "all" && "tab-active"]}
|
|
>
|
|
All Alerts
|
|
</.link>
|
|
<.link
|
|
patch={~p"/orgs/#{@current_organization.slug}/alerts?filter=active"}
|
|
class={["tab", @filter == "active" && "tab-active"]}
|
|
>
|
|
Active Alerts
|
|
</.link>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-8">
|
|
<%= if Enum.empty?(@alerts) do %>
|
|
<div class="text-center py-12">
|
|
<.icon name="hero-bell-slash" class="w-12 h-12 mx-auto text-base-content/40" />
|
|
<h3 class="mt-2 text-sm font-semibold text-base-content/80">No alerts</h3>
|
|
<p class="mt-1 text-sm text-base-content/60">
|
|
<%= 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={[
|
|
"card bg-base-200",
|
|
alert.resolved_at && "opacity-60",
|
|
alert.alert_type == :equipment_down && is_nil(alert.resolved_at) &&
|
|
"border-l-4 border-error"
|
|
]}>
|
|
<div class="card-body">
|
|
<div class="flex items-start justify-between">
|
|
<div class="flex-1">
|
|
<div class="flex items-center gap-3">
|
|
<span class={[
|
|
"badge badge-lg",
|
|
alert.alert_type == :equipment_down && "badge-error",
|
|
alert.alert_type == :equipment_up && "badge-success"
|
|
]}>
|
|
<%= case alert.alert_type do %>
|
|
<% :equipment_down -> %>
|
|
<.icon name="hero-exclamation-triangle" class="w-4 h-4 mr-1" />
|
|
Equipment Down
|
|
<% :equipment_up -> %>
|
|
<.icon name="hero-check-circle" class="w-4 h-4 mr-1" />
|
|
Equipment Recovered
|
|
<% end %>
|
|
</span>
|
|
|
|
<%= if alert.resolved_at do %>
|
|
<span class="badge badge-ghost">Resolved</span>
|
|
<% end %>
|
|
|
|
<%= if alert.acknowledged_at do %>
|
|
<span class="badge badge-info badge-sm">Acknowledged</span>
|
|
<% end %>
|
|
</div>
|
|
|
|
<h3 class="font-semibold mt-3">
|
|
<.link
|
|
navigate={
|
|
~p"/orgs/#{@current_organization.slug}/equipment/#{alert.equipment.id}"
|
|
}
|
|
class="link link-hover"
|
|
>
|
|
{alert.equipment.name}
|
|
</.link>
|
|
</h3>
|
|
|
|
<p class="text-sm text-base-content/70 mt-1">{alert.message}</p>
|
|
|
|
<div class="text-xs text-base-content/50 mt-2 space-y-1">
|
|
<div>
|
|
<strong>Triggered:</strong>
|
|
{Calendar.strftime(alert.triggered_at, "%Y-%m-%d %H:%M:%S UTC")}
|
|
</div>
|
|
|
|
<%= if alert.acknowledged_at do %>
|
|
<div>
|
|
<strong>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>Resolved:</strong>
|
|
{Calendar.strftime(alert.resolved_at, "%Y-%m-%d %H:%M:%S UTC")}
|
|
</div>
|
|
<% end %>
|
|
|
|
<div>
|
|
<strong>Site:</strong>
|
|
<.link
|
|
navigate={
|
|
~p"/orgs/#{@current_organization.slug}/sites/#{alert.equipment.site.id}"
|
|
}
|
|
class="link link-hover"
|
|
>
|
|
{alert.equipment.site.name}
|
|
</.link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex gap-2">
|
|
<%= if is_nil(alert.acknowledged_at) && is_nil(alert.resolved_at) do %>
|
|
<.button
|
|
phx-click="acknowledge"
|
|
phx-value-id={alert.id}
|
|
class="btn-sm btn-primary"
|
|
>
|
|
<.icon name="hero-check" class="w-4 h-4" /> Acknowledge
|
|
</.button>
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
<% end %>
|
|
</div>
|