Group billing providers on settings integrations tab

Add 'Billing & Subscriber Management' section header with 'Choose one'
badge and 'Other Integrations' divider on the settings page integrations
tab. Reorder providers: billing first (Gaiia, Sonar, Splynx, VISP),
then QoE/incidents/infrastructure.
This commit is contained in:
Graham McIntire 2026-02-16 08:34:44 -06:00
parent 6331bc9400
commit 541b418d57
2 changed files with 49 additions and 22 deletions

View file

@ -16,13 +16,10 @@ defmodule ToweropsWeb.Org.SettingsLive do
require Logger
@billing_provider_ids ~w(gaiia sonar splynx visp)
@providers [
%{
id: "preseem",
name: "Preseem",
description: "QoE monitoring and subscriber experience analytics for wireless ISPs.",
icon: "hero-signal"
},
# Billing providers (mutually exclusive — grouped first)
%{
id: "gaiia",
name: "Gaiia",
@ -30,20 +27,6 @@ defmodule ToweropsWeb.Org.SettingsLive do
"Billing and subscriber management. Enables outage impact analysis, inventory reconciliation, and subscriber-aware monitoring.",
icon: "hero-user-group"
},
%{
id: "pagerduty",
name: "PagerDuty",
description:
"Incident management and on-call alerting. Automatically triggers, acknowledges, and resolves PagerDuty incidents from TowerOps alerts.",
icon: "hero-bell-alert"
},
%{
id: "netbox",
name: "NetBox",
description:
"Infrastructure source of truth. Sync devices, sites, IP addresses, and interfaces between TowerOps and your NetBox instance.",
icon: "hero-server-stack"
},
%{
id: "sonar",
name: "Sonar",
@ -63,6 +46,27 @@ defmodule ToweropsWeb.Org.SettingsLive do
name: "VISP",
description: "Cloud-based ISP management. Sync subscribers, sites, equipment, and MRR data from VISP.",
icon: "hero-cloud"
},
# Other integrations
%{
id: "preseem",
name: "Preseem",
description: "QoE monitoring and subscriber experience analytics for wireless ISPs.",
icon: "hero-signal"
},
%{
id: "pagerduty",
name: "PagerDuty",
description:
"Incident management and on-call alerting. Automatically triggers, acknowledges, and resolves PagerDuty incidents from TowerOps alerts.",
icon: "hero-bell-alert"
},
%{
id: "netbox",
name: "NetBox",
description:
"Infrastructure source of truth. Sync devices, sites, IP addresses, and interfaces between TowerOps and your NetBox instance.",
icon: "hero-server-stack"
}
]
@ -94,6 +98,7 @@ defmodule ToweropsWeb.Org.SettingsLive do
|> assign(:invite_form, to_form(%{"email" => "", "role" => "technician"}))
# Integration assigns - loaded lazily when tab is selected
|> assign(:providers, @providers)
|> assign(:billing_provider_ids, @billing_provider_ids)
|> assign(:integrations, %{})
|> assign(:configuring, nil)
|> assign(:integration_form, nil)

View file

@ -839,8 +839,29 @@
<%= if @active_tab == "integrations" do %>
<div class="mt-8 space-y-5">
<div
:for={provider <- @providers}
<%= for {provider, idx} <- Enum.with_index(@providers) do %>
<%!-- Section headers --%>
<%= if idx == 0 do %>
<div class="flex flex-wrap items-center gap-3">
<h3 class="text-sm font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400">
Billing & Subscriber Management
</h3>
<span class="inline-flex items-center gap-1 rounded-full bg-indigo-100 px-2.5 py-0.5 text-xs font-semibold text-indigo-700 dark:bg-indigo-900/40 dark:text-indigo-300">
<.icon name="hero-arrow-path" class="h-3 w-3" /> Choose one
</span>
<span class="text-xs text-gray-500 dark:text-gray-400">
— only one billing platform can be active at a time
</span>
</div>
<% end %>
<%= if provider.id not in @billing_provider_ids and (idx == 0 or Enum.at(@providers, idx - 1).id in @billing_provider_ids) do %>
<div class="pt-4 mt-4 border-t border-gray-200 dark:border-white/10">
<h3 class="text-sm font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400">
Other Integrations
</h3>
</div>
<% end %>
<div
class={[
"relative overflow-hidden rounded-xl border bg-white shadow-sm transition-all dark:bg-white/[0.03]",
cond do
@ -2027,6 +2048,7 @@
</div>
<% end %>
</div>
<% end %>
</div>
<% end %>
</Layouts.authenticated>