<.icon
name="hero-light-bulb"
class="mx-auto h-16 w-16 text-blue-500 dark:text-blue-400"
/>
Let's get started!
Follow these steps to set up your network monitoring:
<%= if @current_scope.organization.use_sites do %>
1
Create a Site
Sites represent your physical locations (offices, data centers, towers, etc.)
2
Add Devices
Add network devices (routers, switches, servers) to your sites
<% else %>
1
Add Devices
Add network devices (routers, switches, servers) to monitor
<% end %>
{if @current_scope.organization.use_sites, do: "3", else: "2"}
Monitor & Receive Alerts
Towerops will automatically monitor your devices and alert you of issues
<%= if @current_scope.organization.use_sites do %>
<.button navigate={~p"/sites/new"} variant="primary">
<.icon name="hero-plus" class="h-5 w-5" /> Create Your First Site
<% else %>
<.button navigate={~p"/devices/new"} variant="primary">
<.icon name="hero-plus" class="h-5 w-5" /> Add Your First Device
<% end %>
<% else %>
<%!-- Section A: Health Overview --%>
<%!-- Health Score --%>
Health Score
{@summary.health_score}
<%!-- Network Uptime --%>
Network Uptime
{if @uptime_percentage == 100.0, do: "100", else: :erlang.float_to_binary(@uptime_percentage, decimals: 1)}%
{@device_up}/{@device_count} devices up
<%!-- Active Alerts --%>
<.link
navigate={~p"/alerts"}
class="rounded-lg border border-gray-200 bg-white p-4 shadow-sm transition-shadow hover:shadow-md dark:border-white/10 dark:bg-gray-800/50"
>
Active Alerts
0 && "text-red-600 dark:text-red-500") ||
"text-gray-900 dark:text-white"
]}>
{@total_alert_count}
<%!-- Devices --%>
<.link
navigate={~p"/devices"}
class="rounded-lg border border-gray-200 bg-white p-4 shadow-sm transition-shadow hover:shadow-md dark:border-white/10 dark:bg-gray-800/50"
>
Devices
{@device_count}
{@device_up} Up
{@device_down} Down
{@device_unknown} Unknown
<%!-- Subscribers (only when Gaiia data exists) --%>
<%= if @has_subscribers do %>
Subscribers
{format_number(@summary.subscribers.total)}
{format_mrr(@summary.subscribers.total_mrr)}/mo MRR
<%!-- MRR at Risk --%>
MRR at Risk
{format_mrr(@impact_summary.mrr_at_risk)}
0} class="mt-1 text-sm text-red-600 dark:text-red-400">
{format_number(@impact_summary.subscribers_affected)} subscribers affected
<% end %>
<%!-- Sites (if enabled) --%>
<%= if @current_scope.organization.use_sites do %>
<.link
navigate={~p"/sites"}
class="rounded-lg border border-gray-200 bg-white p-4 shadow-sm transition-shadow hover:shadow-md dark:border-white/10 dark:bg-gray-800/50"
>
Sites
{@sites_count}
<% end %>
<%!-- Insights --%>
Insights
{@summary.insights.critical + @summary.insights.warning + @summary.insights.info}
<%= if @summary.insights.critical > 0 do %>
{@summary.insights.critical} critical
<% end %>
<%= if @summary.insights.warning > 0 do %>
{@summary.insights.warning} warning
<% end %>
<%= if @summary.insights.info > 0 do %>
{@summary.insights.info} info
<% end %>
<%!-- Quick Actions --%>
<.link navigate={~p"/devices/new"} class="btn btn-outline btn-sm gap-1.5">
<.icon name="hero-plus-circle" class="h-4 w-4" /> Add Device
<.link navigate={~p"/discovery"} class="btn btn-outline btn-sm gap-1.5">
<.icon name="hero-magnifying-glass-circle" class="h-4 w-4" /> Run Discovery
<.link navigate={~p"/alerts"} class="btn btn-outline btn-sm gap-1.5">
<.icon name="hero-bell-alert" class="h-4 w-4" /> View Alerts
<.link navigate={~p"/subscribers/trace"} class="btn btn-outline btn-sm gap-1.5">
<.icon name="hero-signal" class="h-4 w-4" /> Subscriber Trace
<%!-- Active Incidents (sorted by revenue impact) --%>
<%= if @active_incidents != [] do %>
<%!-- Left: Alert Feed (3 cols) --%>
<.icon name="hero-bell-alert" class="h-5 w-5 text-red-500" />
Active Alerts
<.link
navigate={~p"/alerts"}
class="text-sm font-medium text-blue-600 hover:text-blue-700 dark:text-blue-500 dark:hover:text-blue-400"
>
View All →
<%= if @active_alerts == [] do %>
<.icon name="hero-check-circle" class="mx-auto h-10 w-10 text-green-500" />
No active alerts
<% else %>
<.icon name="hero-exclamation-triangle" class="h-3.5 w-3.5" /> Device Down
<%= if alert.acknowledged_at do %>
Acknowledged
<% end %>
<.link
navigate={~p"/devices/#{alert.device.id}"}
class="hover:text-blue-600 hover:underline dark:hover:text-blue-400"
>
{alert.device.name}
{alert.message}
<%!-- Gaiia impact badges --%>
<%= if alert.gaiia_impact && alert.gaiia_impact["total_subscribers"] && alert.gaiia_impact["total_subscribers"] > 0 do %>
<.icon name="hero-users" class="h-3 w-3" />
{alert.gaiia_impact["total_subscribers"]} affected
<%= if alert.gaiia_impact["total_mrr"] && alert.gaiia_impact["total_mrr"] != "0" do %>
<.icon name="hero-currency-dollar" class="h-3 w-3" />
${alert.gaiia_impact["total_mrr"]}/mo
<% end %>
<% end %>
<.timestamp datetime={alert.triggered_at} />
at
<.link
navigate={~p"/sites/#{alert.device.site.id}"}
class="text-blue-600 hover:text-blue-700 dark:text-blue-400"
>
{alert.device.site.name}
<%= if is_nil(alert.acknowledged_at) && is_nil(alert.resolved_at) do %>
Acknowledge
<% end %>
<%= if @total_alert_count > 20 do %>
+ {@total_alert_count - 20} more alerts.
<.link
navigate={~p"/alerts"}
class="font-medium text-blue-600 hover:text-blue-700 dark:text-blue-400"
>
View All
<% end %>
<% end %>
<%!-- Recent Config Changes --%>
<%= if Enum.any?(@recent_config_changes) do %>
<.icon name="hero-document-text" class="h-4 w-4 text-orange-500" />
Recent Config Changes
<.link
navigate={~p"/config-changes"}
class="text-xs font-medium text-blue-600 hover:text-blue-700 dark:text-blue-500 dark:hover:text-blue-400"
>
View All →
<%= for change <- @recent_config_changes do %>
<.link
navigate={~p"/devices/#{change.device_id}/config-timeline"}
class="flex items-center gap-3 p-2 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors"
>
{if change.device, do: change.device.name, else: "Unknown Device"}
{Calendar.strftime(change.changed_at, "%b %d %H:%M")} · {change.change_size} lines · {Enum.join(Enum.take(change.sections_changed, 2), ", ")}
<% end %>
<% end %>
<%!-- Recent Activity Mini-Feed --%>
<%= if assigns[:recent_activity] && @recent_activity != [] do %>
<.icon name="hero-clock" class="h-4 w-4 text-blue-500" />
Recent Activity
<.link
navigate={~p"/activity"}
class="text-xs font-medium text-blue-600 hover:text-blue-700 dark:text-blue-500 dark:hover:text-blue-400"
>
View All →
{activity.description}
{Calendar.strftime(activity.inserted_at, "%b %d %H:%M")}
<%= if Map.get(activity, :actor_name) do %>
by {activity.actor_name}
<% end %>
<% end %>
<%!-- Right: Insights Feed (2 cols) --%>
<.icon name="hero-light-bulb" class="h-5 w-5 text-yellow-500" />
Insights
<.link
navigate={~p"/insights"}
class="text-sm font-medium text-blue-600 hover:text-blue-700 dark:text-blue-500 dark:hover:text-blue-400"
>
View All →
<%!-- Source filter pills --%>
<.link
patch={~p"/dashboard"}
class={[
"rounded-md px-2.5 py-1 text-xs font-medium",
if(is_nil(@insight_source),
do: "bg-gray-200 text-gray-800 dark:bg-white/20 dark:text-white",
else: "text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-white/10"
)
]}
>
All
<.link
:for={source <- ~w(preseem snmp gaiia system)}
patch={~p"/dashboard?insight_source=#{source}"}
class={[
"rounded-md px-2.5 py-1 text-xs font-medium",
if(@insight_source == source,
do: "bg-gray-200 text-gray-800 dark:bg-white/20 dark:text-white",
else: "text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-white/10"
)
]}
>
{source}
<%= if @insights == [] do %>
<.icon
name="hero-light-bulb"
class="mx-auto h-10 w-10 text-gray-400 dark:text-gray-500"
/>
No active insights
<% else %>
{insight.urgency}
{insight.source}
<.link
navigate={~p"/insights?source=#{insight.source}"}
class="hover:text-blue-600 hover:underline dark:hover:text-blue-400"
>
{insight.title}
<%= if insight.description do %>
{insight.description}
<% end %>
<.icon name="hero-x-mark" class="h-4 w-4" />
<% end %>
<%!-- Section D: Site Health Grid --%>
<%= if @current_scope.organization.use_sites && @site_impact_summaries != [] do %>
<.icon name="hero-map-pin" class="h-5 w-5 text-blue-500" />
Site Health
<.link
navigate={~p"/sites"}
class="text-sm font-medium text-blue-600 hover:text-blue-700 dark:text-blue-500 dark:hover:text-blue-400"
>
View All Sites →
<.link
:for={site <- @site_impact_summaries}
navigate={~p"/sites/#{site.site_id}"}
class={[
"rounded-lg border p-4 shadow-sm transition-shadow hover:shadow-md",
site_health_border(site.site_health)
]}
>
{site.name}
{site.device_count} devices
<%= if site.devices_down > 0 do %>
{site.devices_down} down
<% end %>
<%= if site.avg_qoe do %>
QoE {format_qoe(site.avg_qoe)}
<% end %>
<%= if site.subscribers do %>
<.icon name="hero-users" class="h-3.5 w-3.5" />
{site.subscribers} subscribers
<%= if site.mrr do %>
{format_mrr(site.mrr)}/mo
<% end %>
<% end %>
<%= if site.subscribers_affected > 0 do %>
<.icon name="hero-exclamation-triangle" class="h-3.5 w-3.5" />
{format_number(site.subscribers_affected)} affected
<%= if mrr_at_risk_positive?(site.mrr_at_risk) do %>
{format_mrr(site.mrr_at_risk)}/mo at risk
<% end %>
<% end %>
<% end %>
<% end %>