- 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)
56 lines
1.8 KiB
Text
56 lines
1.8 KiB
Text
<.header>
|
|
{@page_title}
|
|
<:subtitle>Manage your site locations and hierarchy</:subtitle>
|
|
<:actions>
|
|
<.link
|
|
navigate={~p"/orgs/#{@current_organization.slug}/sites/new"}
|
|
class="btn btn-primary"
|
|
>
|
|
<.icon name="hero-plus" class="w-5 h-5" /> New Site
|
|
</.link>
|
|
</:actions>
|
|
</.header>
|
|
|
|
<div class="mt-8">
|
|
<%= if @sites == [] do %>
|
|
<div class="text-center py-12">
|
|
<.icon name="hero-building-office" class="mx-auto w-12 h-12 text-base-content/40" />
|
|
<h3 class="mt-2 text-sm font-semibold text-base-content">No sites</h3>
|
|
<p class="mt-1 text-sm text-base-content/60">Get started by creating your first site.</p>
|
|
<div class="mt-6">
|
|
<.link
|
|
navigate={~p"/orgs/#{@current_organization.slug}/sites/new"}
|
|
class="btn btn-primary"
|
|
>
|
|
<.icon name="hero-plus" class="w-5 h-5" /> New Site
|
|
</.link>
|
|
</div>
|
|
</div>
|
|
<% else %>
|
|
<div class="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
|
<div :for={site <- @sites} class="card bg-base-100 shadow">
|
|
<div class="card-body">
|
|
<h3 class="card-title">{site.name}</h3>
|
|
<%= if site.location do %>
|
|
<p class="text-sm text-base-content/60">
|
|
<.icon name="hero-map-pin" class="w-4 h-4 inline" /> {site.location}
|
|
</p>
|
|
<% end %>
|
|
<%= if site.parent_site do %>
|
|
<p class="text-xs text-base-content/40">
|
|
Parent: {site.parent_site.name}
|
|
</p>
|
|
<% end %>
|
|
<div class="card-actions justify-end mt-2">
|
|
<.link
|
|
navigate={~p"/orgs/#{@current_organization.slug}/sites/#{site.id}"}
|
|
class="btn btn-sm"
|
|
>
|
|
View
|
|
</.link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<% end %>
|
|
</div>
|