feat: add API key setup help to integration configuration panels
Add setup_help info boxes to each integration provider showing where to create API keys, step-by-step instructions, required permissions, and example URL patterns.
This commit is contained in:
parent
5e5da89f3a
commit
198f2c3cbc
2 changed files with 176 additions and 14 deletions
|
|
@ -27,27 +27,67 @@ defmodule ToweropsWeb.Org.SettingsLive do
|
|||
name: "Gaiia",
|
||||
description:
|
||||
"Billing and subscriber management. Enables outage impact analysis, inventory reconciliation, and subscriber-aware monitoring.",
|
||||
icon: "hero-user-group"
|
||||
icon: "hero-user-group",
|
||||
setup_help: %{
|
||||
url_pattern: "https://app.gaiia.com/{your-org}/admin/apiKeys",
|
||||
steps: [
|
||||
"Log into Gaiia and go to **Admin** → **API Keys**",
|
||||
"Click **Create API Key**",
|
||||
"Give it a descriptive name (e.g. \"TowerOps\")",
|
||||
"Copy the generated API key and paste it below"
|
||||
],
|
||||
permissions:
|
||||
"Read-only access. The key only needs permission to read accounts, subscriptions, and inventory data."
|
||||
}
|
||||
},
|
||||
%{
|
||||
id: "sonar",
|
||||
name: "Sonar",
|
||||
description:
|
||||
"Billing and subscriber management. Sync accounts, network sites, and inventory from your Sonar instance.",
|
||||
icon: "hero-currency-dollar"
|
||||
icon: "hero-currency-dollar",
|
||||
setup_help: %{
|
||||
url_pattern: "https://{your-instance}.sonar.software/admin/users/{your-user-id}",
|
||||
steps: [
|
||||
"Log into Sonar and go to **Settings** → **Security** → **API Tokens** (or your user profile → API Tokens)",
|
||||
"Click **Create Token**",
|
||||
"Name it (e.g. \"TowerOps\") and copy the generated token"
|
||||
],
|
||||
permissions:
|
||||
"Requires a **read-only** personal access token. The token needs access to: Accounts, Network Sites, Inventory Items, and Address data."
|
||||
}
|
||||
},
|
||||
%{
|
||||
id: "splynx",
|
||||
name: "Splynx",
|
||||
description:
|
||||
"ISP billing and management platform. Sync customers, internet services, and network routers from Splynx.",
|
||||
icon: "hero-banknotes"
|
||||
icon: "hero-banknotes",
|
||||
setup_help: %{
|
||||
url_pattern: "https://{your-instance}.splynx.app/admin/administration/api-keys",
|
||||
steps: [
|
||||
"Log into Splynx and go to **Administration** → **API Keys**",
|
||||
"Click **Add** to create a new API key",
|
||||
"Copy both the **API Key** and **API Secret**"
|
||||
],
|
||||
permissions:
|
||||
"Requires read access to **Customers**, **Internet Services**, and **Routers**. No write permissions needed."
|
||||
}
|
||||
},
|
||||
%{
|
||||
id: "visp",
|
||||
name: "VISP",
|
||||
description: "Cloud-based ISP management. Sync subscribers, sites, equipment, and MRR data from VISP.",
|
||||
icon: "hero-cloud"
|
||||
icon: "hero-cloud",
|
||||
setup_help: %{
|
||||
url_pattern: "https://app.visp.net/settings/api",
|
||||
steps: [
|
||||
"Log into VISP and go to **Settings** → **API**",
|
||||
"Click **Generate New Key**",
|
||||
"Name it (e.g. \"TowerOps\") and copy the generated API key"
|
||||
],
|
||||
permissions: "Requires read-only API access to **Subscribers**, **Sites**, **Equipment**, and **Billing** data."
|
||||
}
|
||||
},
|
||||
# Quality of Experience
|
||||
%{
|
||||
|
|
@ -55,7 +95,16 @@ defmodule ToweropsWeb.Org.SettingsLive do
|
|||
name: "Preseem",
|
||||
description: "QoE monitoring and subscriber experience analytics for wireless ISPs.",
|
||||
icon: "hero-signal",
|
||||
category: "Quality of Experience"
|
||||
category: "Quality of Experience",
|
||||
setup_help: %{
|
||||
url_pattern: "https://app.preseem.com/settings/api",
|
||||
steps: [
|
||||
"Log into Preseem and go to **Settings** → **API**",
|
||||
"Click **Generate API Key**",
|
||||
"Copy the generated key and paste it below"
|
||||
],
|
||||
permissions: "Read-only access. The key needs permission to read subscriber QoE metrics and access point data."
|
||||
}
|
||||
},
|
||||
# Incident Management
|
||||
%{
|
||||
|
|
@ -73,7 +122,18 @@ defmodule ToweropsWeb.Org.SettingsLive do
|
|||
description:
|
||||
"Infrastructure source of truth. Sync devices, sites, IP addresses, and interfaces between TowerOps and your NetBox instance.",
|
||||
icon: "hero-server-stack",
|
||||
category: "Infrastructure & IPAM"
|
||||
category: "Infrastructure & IPAM",
|
||||
setup_help: %{
|
||||
url_pattern: "https://{your-netbox-instance}/user/api-tokens/",
|
||||
steps: [
|
||||
"Log into NetBox and go to your **profile** (top right) → **API Tokens**",
|
||||
"Click **Add a token**",
|
||||
"Optionally set an expiry date and description (e.g. \"TowerOps\")",
|
||||
"Copy the generated token"
|
||||
],
|
||||
permissions:
|
||||
"Requires **read** permission at minimum. If you want to push data to NetBox (bidirectional sync), the token also needs **write** permission."
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
|
@ -686,6 +746,10 @@ defmodule ToweropsWeb.Org.SettingsLive do
|
|||
|
||||
defp get_credential(_integration, _key), do: ""
|
||||
|
||||
defp format_help_step(text) do
|
||||
String.replace(text, ~r/\*\*(.+?)\*\*/, "<strong>\\1</strong>")
|
||||
end
|
||||
|
||||
defp current_integration(socket) do
|
||||
provider = socket.assigns.configuring
|
||||
Map.get(socket.assigns.integrations, provider)
|
||||
|
|
|
|||
|
|
@ -1190,10 +1190,7 @@
|
|||
</h4>
|
||||
</div>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400 mb-4 ml-6">
|
||||
{t(
|
||||
"Your NetBox instance URL and API token. The token needs read permission at minimum."
|
||||
)}
|
||||
{t("Write permission is required if you want to push data to NetBox.")}
|
||||
{t("Your NetBox instance URL and API token.")}
|
||||
</p>
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||
<div>
|
||||
|
|
@ -1223,6 +1220,31 @@
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 rounded-lg bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800/50 p-4">
|
||||
<h4 class="flex items-center gap-1.5 text-xs font-semibold text-blue-900 dark:text-blue-300 mb-2">
|
||||
<.icon name="hero-information-circle" class="h-4 w-4" />
|
||||
{t("How to create your API token")}
|
||||
</h4>
|
||||
<ol class="list-decimal list-inside space-y-1 text-xs text-blue-800 dark:text-blue-300 ml-5">
|
||||
<%= for step <- provider.setup_help.steps do %>
|
||||
<li>{raw(format_help_step(step))}</li>
|
||||
<% end %>
|
||||
</ol>
|
||||
<p class="mt-2.5 text-xs text-blue-700 dark:text-blue-400 ml-5">
|
||||
<.icon
|
||||
name="hero-shield-check"
|
||||
class="h-3.5 w-3.5 inline -mt-0.5"
|
||||
/>
|
||||
{raw(format_help_step(provider.setup_help.permissions))}
|
||||
</p>
|
||||
<p class="mt-2 text-xs text-blue-600/80 dark:text-blue-400/70 ml-5">
|
||||
<.icon
|
||||
name="hero-arrow-top-right-on-square"
|
||||
class="h-3 w-3 inline -mt-0.5"
|
||||
/> Example URL:
|
||||
<code class="font-mono">{provider.setup_help.url_pattern}</code>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%!-- Sync Direction Section --%>
|
||||
|
|
@ -1577,7 +1599,7 @@
|
|||
</h4>
|
||||
</div>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400 mb-4 ml-6">
|
||||
{t("Your Sonar instance URL and API token from the Sonar admin panel.")}
|
||||
{t("Your Sonar instance URL and API token.")}
|
||||
</p>
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||
<div>
|
||||
|
|
@ -1607,6 +1629,31 @@
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 rounded-lg bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800/50 p-4">
|
||||
<h4 class="flex items-center gap-1.5 text-xs font-semibold text-blue-900 dark:text-blue-300 mb-2">
|
||||
<.icon name="hero-information-circle" class="h-4 w-4" />
|
||||
{t("How to create your API token")}
|
||||
</h4>
|
||||
<ol class="list-decimal list-inside space-y-1 text-xs text-blue-800 dark:text-blue-300 ml-5">
|
||||
<%= for step <- provider.setup_help.steps do %>
|
||||
<li>{raw(format_help_step(step))}</li>
|
||||
<% end %>
|
||||
</ol>
|
||||
<p class="mt-2.5 text-xs text-blue-700 dark:text-blue-400 ml-5">
|
||||
<.icon
|
||||
name="hero-shield-check"
|
||||
class="h-3.5 w-3.5 inline -mt-0.5"
|
||||
/>
|
||||
{raw(format_help_step(provider.setup_help.permissions))}
|
||||
</p>
|
||||
<p class="mt-2 text-xs text-blue-600/80 dark:text-blue-400/70 ml-5">
|
||||
<.icon
|
||||
name="hero-arrow-top-right-on-square"
|
||||
class="h-3 w-3 inline -mt-0.5"
|
||||
/> Example URL:
|
||||
<code class="font-mono">{provider.setup_help.url_pattern}</code>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-gray-200 pt-5 dark:border-white/10">
|
||||
|
|
@ -1682,9 +1729,7 @@
|
|||
</h4>
|
||||
</div>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400 mb-4 ml-6">
|
||||
{t(
|
||||
"Your Splynx instance URL, API key, and API secret. Find these in Splynx under Administration → API Keys."
|
||||
)}
|
||||
{t("Your Splynx instance URL, API key, and API secret.")}
|
||||
</p>
|
||||
<div class="grid grid-cols-1 gap-4">
|
||||
<div>
|
||||
|
|
@ -1729,6 +1774,31 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 rounded-lg bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800/50 p-4">
|
||||
<h4 class="flex items-center gap-1.5 text-xs font-semibold text-blue-900 dark:text-blue-300 mb-2">
|
||||
<.icon name="hero-information-circle" class="h-4 w-4" />
|
||||
{t("How to create your API key")}
|
||||
</h4>
|
||||
<ol class="list-decimal list-inside space-y-1 text-xs text-blue-800 dark:text-blue-300 ml-5">
|
||||
<%= for step <- provider.setup_help.steps do %>
|
||||
<li>{raw(format_help_step(step))}</li>
|
||||
<% end %>
|
||||
</ol>
|
||||
<p class="mt-2.5 text-xs text-blue-700 dark:text-blue-400 ml-5">
|
||||
<.icon
|
||||
name="hero-shield-check"
|
||||
class="h-3.5 w-3.5 inline -mt-0.5"
|
||||
/>
|
||||
{raw(format_help_step(provider.setup_help.permissions))}
|
||||
</p>
|
||||
<p class="mt-2 text-xs text-blue-600/80 dark:text-blue-400/70 ml-5">
|
||||
<.icon
|
||||
name="hero-arrow-top-right-on-square"
|
||||
class="h-3 w-3 inline -mt-0.5"
|
||||
/> Example URL:
|
||||
<code class="font-mono">{provider.setup_help.url_pattern}</code>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-gray-200 pt-5 dark:border-white/10">
|
||||
|
|
@ -1826,6 +1896,34 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<%= if Map.has_key?(provider, :setup_help) && provider.id != "pagerduty" do %>
|
||||
<div class="rounded-lg bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800/50 p-4">
|
||||
<h4 class="flex items-center gap-1.5 text-xs font-semibold text-blue-900 dark:text-blue-300 mb-2">
|
||||
<.icon name="hero-information-circle" class="h-4 w-4" />
|
||||
{t("How to create your API key")}
|
||||
</h4>
|
||||
<ol class="list-decimal list-inside space-y-1 text-xs text-blue-800 dark:text-blue-300 ml-5">
|
||||
<%= for step <- provider.setup_help.steps do %>
|
||||
<li>{raw(format_help_step(step))}</li>
|
||||
<% end %>
|
||||
</ol>
|
||||
<p class="mt-2.5 text-xs text-blue-700 dark:text-blue-400 ml-5">
|
||||
<.icon
|
||||
name="hero-shield-check"
|
||||
class="h-3.5 w-3.5 inline -mt-0.5"
|
||||
/>
|
||||
{raw(format_help_step(provider.setup_help.permissions))}
|
||||
</p>
|
||||
<p class="mt-2 text-xs text-blue-600/80 dark:text-blue-400/70 ml-5">
|
||||
<.icon
|
||||
name="hero-arrow-top-right-on-square"
|
||||
class="h-3 w-3 inline -mt-0.5"
|
||||
/> Example URL:
|
||||
<code class="font-mono">{provider.setup_help.url_pattern}</code>
|
||||
</p>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= if provider.id == "pagerduty" do %>
|
||||
<div class="rounded-lg bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800/50 p-4">
|
||||
<h4 class="flex items-center gap-1.5 text-xs font-semibold text-blue-900 dark:text-blue-300 mb-2">
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue