towerops/lib/towerops_web/live/site_live/show.html.heex
Graham McIntire 1bd72dac78
1. Sites Management
- Sites schema with hierarchical parent-child relationships
  - CRUD operations for sites
  - Sites context with helper functions
  - LiveView pages:
    - /orgs/:slug/sites - List all sites
    - /orgs/:slug/sites/new - Create new site
    - /orgs/:slug/sites/:id - View site details
    - /orgs/:slug/sites/:id/edit - Edit site
  - Support for site locations and descriptions
  - Site tree builder for hierarchy visualization

  2. Equipment Management
  - Equipment schema with monitoring fields
  - IP address validation (IPv4 & IPv6)
  - Equipment status tracking (up/down/unknown)
  - Customizable check intervals per equipment
  - Equipment context with CRUD operations
  - LiveView pages:
    - /orgs/:slug/equipment - List all equipment
    - /orgs/:slug/equipment/new - Add equipment
    - /orgs/:slug/equipment/:id - View equipment details
    - /orgs/:slug/equipment/:id/edit - Edit equipment
  - Equipment can be added from site pages
  - Status badges and last checked timestamps

  3. Database Schema
  - sites table with self-referencing parent_site_id
  - equipment table with status tracking
  - All migrations run successfully
  - Proper indexes on foreign keys and status

  4. Features Implemented
  -  IP address validation using :inet.parse_address
  -  Site hierarchy with parent-child relationships
  -  Equipment linked to sites
  -  Monitoring enabled/disabled per equipment
  -  Customizable check intervals (30s - 3600s)
  -  Status tracking (up/down/unknown)
  -  Timestamps for last check and last status change
  -  Organization-scoped data (users only see their org's data)
2025-12-21 13:39:19 -06:00

108 lines
3.3 KiB
Text

<.header>
{@page_title}
<:subtitle>{@site.location}</:subtitle>
<:actions>
<.link
navigate={~p"/orgs/#{@current_organization.slug}/sites/#{@site.id}/edit"}
class="btn btn-sm"
>
<.icon name="hero-pencil" class="w-4 h-4" /> Edit
</.link>
<.button phx-click="delete" data-confirm="Are you sure?" class="btn-error btn-sm">
<.icon name="hero-trash" class="w-4 h-4" /> Delete
</.button>
</:actions>
</.header>
<div class="mt-8 grid gap-6 md:grid-cols-2">
<div>
<h3 class="text-lg font-semibold mb-4">Site Details</h3>
<dl class="space-y-2">
<%= if @site.parent_site do %>
<div>
<dt class="text-sm font-medium text-base-content/60">Parent Site</dt>
<dd class="mt-1">
<.link
navigate={~p"/orgs/#{@current_organization.slug}/sites/#{@site.parent_site.id}"}
class="link link-primary"
>
{@site.parent_site.name}
</.link>
</dd>
</div>
<% end %>
<%= if @site.location do %>
<div>
<dt class="text-sm font-medium text-base-content/60">Location</dt>
<dd class="mt-1">{@site.location}</dd>
</div>
<% end %>
<%= if @site.description do %>
<div>
<dt class="text-sm font-medium text-base-content/60">Description</dt>
<dd class="mt-1">{@site.description}</dd>
</div>
<% end %>
</dl>
<%= if @site.child_sites != [] do %>
<div class="mt-6">
<h4 class="text-sm font-semibold mb-2">Child Sites</h4>
<ul class="space-y-1">
<li :for={child <- @site.child_sites}>
<.link
navigate={~p"/orgs/#{@current_organization.slug}/sites/#{child.id}"}
class="link link-primary text-sm"
>
{child.name}
</.link>
</li>
</ul>
</div>
<% end %>
</div>
<div>
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold">Equipment</h3>
<.link
navigate={~p"/orgs/#{@current_organization.slug}/equipment/new?site_id=#{@site.id}"}
class="btn btn-sm btn-primary"
>
<.icon name="hero-plus" class="w-4 h-4" /> Add Equipment
</.link>
</div>
<%= if @equipment == [] do %>
<p class="text-sm text-base-content/60">No equipment at this site yet.</p>
<% else %>
<div class="space-y-2">
<div
:for={eq <- @equipment}
class="flex items-center justify-between p-3 bg-base-200 rounded"
>
<div>
<p class="font-medium">{eq.name}</p>
<p class="text-sm text-base-content/60">{eq.ip_address}</p>
</div>
<div class="flex items-center gap-2">
<span class={[
"badge badge-sm",
eq.status == :up && "badge-success",
eq.status == :down && "badge-error",
eq.status == :unknown && "badge-ghost"
]}>
{eq.status |> to_string() |> String.upcase()}
</span>
<.link
navigate={~p"/orgs/#{@current_organization.slug}/equipment/#{eq.id}"}
class="btn btn-xs"
>
View
</.link>
</div>
</div>
</div>
<% end %>
</div>
</div>