<.link
- navigate={
- ~p"/orgs/#{@current_organization.slug}/devices/#{@device.id}/graph/voltage"
- }
+ navigate={~p"/devices/#{@device.id}/graph/voltage"}
class="hover:text-blue-600 dark:hover:text-blue-400 hover:underline"
>
{sensor.sensor_descr}
@@ -482,7 +468,7 @@
|
<.link
navigate={
- ~p"/orgs/#{@current_organization.slug}/devices/#{@device.id}/graph/traffic?interface_id=#{interface.id}"
+ ~p"/devices/#{@device.id}/graph/traffic?interface_id=#{interface.id}"
}
class="hover:text-blue-600 dark:hover:text-blue-400"
>
@@ -569,9 +555,7 @@
|
<%= if neighbor.matched_device do %>
<.link
- navigate={
- ~p"/orgs/#{@current_organization.slug}/devices/#{neighbor.matched_device.id}"
- }
+ navigate={~p"/devices/#{neighbor.matched_device.id}"}
class="font-medium text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300"
>
{neighbor.matched_device.name}
diff --git a/lib/towerops_web/live/graph_live/show.ex b/lib/towerops_web/live/graph_live/show.ex
index 4c0b23fd..2a1cd597 100644
--- a/lib/towerops_web/live/graph_live/show.ex
+++ b/lib/towerops_web/live/graph_live/show.ex
@@ -38,8 +38,7 @@ defmodule ToweropsWeb.GraphLive.Show do
{:noreply,
push_patch(socket,
- to:
- ~p"/orgs/#{socket.assigns.current_organization.slug}/devices/#{socket.assigns.device_id}/graph/#{socket.assigns.sensor_type}?#{params}"
+ to: ~p"/devices/#{socket.assigns.device_id}/graph/#{socket.assigns.sensor_type}?#{params}"
)}
end
diff --git a/lib/towerops_web/live/graph_live/show.html.heex b/lib/towerops_web/live/graph_live/show.html.heex
index 25fa9787..9ca170f1 100644
--- a/lib/towerops_web/live/graph_live/show.html.heex
+++ b/lib/towerops_web/live/graph_live/show.html.heex
@@ -10,7 +10,7 @@
<.link
- navigate={~p"/orgs/#{@current_organization.slug}/devices/#{@device_id}"}
+ navigate={~p"/devices/#{@device_id}"}
class="text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100"
>
<.icon name="hero-arrow-left" class="h-5 w-5" />
diff --git a/lib/towerops_web/live/site_live/form.ex b/lib/towerops_web/live/site_live/form.ex
index 36cec376..0f941551 100644
--- a/lib/towerops_web/live/site_live/form.ex
+++ b/lib/towerops_web/live/site_live/form.ex
@@ -86,7 +86,7 @@ defmodule ToweropsWeb.SiteLive.Form do
{:noreply,
socket
|> put_flash(:info, "Site deleted successfully")
- |> push_navigate(to: ~p"/orgs/#{socket.assigns.organization.slug}/sites")}
+ |> push_navigate(to: ~p"/sites")}
{:error, _} ->
{:noreply, put_flash(socket, :error, "Unable to delete site")}
@@ -115,7 +115,7 @@ defmodule ToweropsWeb.SiteLive.Form do
{:noreply,
socket
|> put_flash(:info, "Site created successfully! Now add your first device.")
- |> push_navigate(to: ~p"/orgs/#{socket.assigns.organization.slug}/sites/#{site.id}")}
+ |> push_navigate(to: ~p"/sites/#{site.id}")}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, :form, to_form(changeset))}
@@ -128,7 +128,7 @@ defmodule ToweropsWeb.SiteLive.Form do
{:noreply,
socket
|> put_flash(:info, "Site updated successfully")
- |> push_navigate(to: ~p"/orgs/#{socket.assigns.organization.slug}/sites")}
+ |> push_navigate(to: ~p"/sites")}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, :form, to_form(changeset))}
diff --git a/lib/towerops_web/live/site_live/form.html.heex b/lib/towerops_web/live/site_live/form.html.heex
index aaed6722..0c3ab7bc 100644
--- a/lib/towerops_web/live/site_live/form.html.heex
+++ b/lib/towerops_web/live/site_live/form.html.heex
@@ -7,8 +7,8 @@
<.link
navigate={
if @live_action == :edit,
- do: ~p"/orgs/#{@current_organization.slug}/sites/#{@site.id}",
- else: ~p"/orgs/#{@current_organization.slug}/sites"
+ do: ~p"/sites/#{@site.id}",
+ else: ~p"/sites"
}
class="inline-flex items-center gap-1 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100"
>
@@ -181,7 +181,7 @@
<.button phx-disable-with="Saving..." variant="primary">Save Site
- <.button navigate={~p"/orgs/#{@current_organization.slug}/sites"}>Cancel
+ <.button navigate={~p"/sites"}>Cancel
diff --git a/lib/towerops_web/live/site_live/index.html.heex b/lib/towerops_web/live/site_live/index.html.heex
index f4d4548e..79764d68 100644
--- a/lib/towerops_web/live/site_live/index.html.heex
+++ b/lib/towerops_web/live/site_live/index.html.heex
@@ -9,7 +9,7 @@
{@page_title}
<:subtitle>Manage your site locations and hierarchy
<:actions>
- <.button navigate={~p"/orgs/#{@current_organization.slug}/sites/new"} variant="primary">
+ <.button navigate={~p"/sites/new"} variant="primary">
<.icon name="hero-plus" class="h-5 w-5" /> New Site
@@ -26,7 +26,7 @@
Get started by creating your first site.
- <.button navigate={~p"/orgs/#{@current_organization.slug}/sites/new"} variant="primary">
+ <.button navigate={~p"/sites/new"} variant="primary">
<.icon name="hero-plus" class="h-5 w-5" /> New Site
@@ -35,7 +35,7 @@
<.link
:for={site <- @sites}
- navigate={~p"/orgs/#{@current_organization.slug}/sites/#{site.id}"}
+ navigate={~p"/sites/#{site.id}"}
class="relative overflow-hidden rounded-lg border border-zinc-200 bg-white p-6 shadow-sm hover:shadow-md transition-shadow dark:border-zinc-800 dark:bg-zinc-900 cursor-pointer"
>
{site.name}
diff --git a/lib/towerops_web/live/site_live/show.html.heex b/lib/towerops_web/live/site_live/show.html.heex
index 2a6eaad5..4f826823 100644
--- a/lib/towerops_web/live/site_live/show.html.heex
+++ b/lib/towerops_web/live/site_live/show.html.heex
@@ -9,7 +9,7 @@
{@page_title}
<:subtitle>{@site.location}
<:actions>
- <.button navigate={~p"/orgs/#{@current_organization.slug}/sites/#{@site.id}/edit"}>
+ <.button navigate={~p"/sites/#{@site.id}/edit"}>
<.icon name="hero-pencil" class="h-4 w-4" /> Edit
@@ -24,7 +24,7 @@
Parent Site
<.link
- navigate={~p"/orgs/#{@current_organization.slug}/sites/#{@site.parent_site.id}"}
+ navigate={~p"/sites/#{@site.parent_site.id}"}
class="text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
>
{@site.parent_site.name}
@@ -52,7 +52,7 @@
-
<.link
- navigate={~p"/orgs/#{@current_organization.slug}/sites/#{child.id}"}
+ navigate={~p"/sites/#{child.id}"}
class="text-sm text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
>
{child.name}
@@ -67,7 +67,7 @@
Device
<.button
- navigate={~p"/orgs/#{@current_organization.slug}/devices/new?site_id=#{@site.id}"}
+ navigate={~p"/devices/new?site_id=#{@site.id}"}
variant="primary"
>
<.icon name="hero-plus" class="h-4 w-4" /> Add Device
@@ -88,7 +88,7 @@
<.button
- navigate={~p"/orgs/#{@current_organization.slug}/devices/new?site_id=#{@site.id}"}
+ navigate={~p"/devices/new?site_id=#{@site.id}"}
variant="primary"
>
<.icon name="hero-plus" class="h-5 w-5" /> Add Device
@@ -99,7 +99,7 @@
<.link
:for={eq <- @device}
- navigate={~p"/orgs/#{@current_organization.slug}/devices/#{eq.id}"}
+ navigate={~p"/devices/#{eq.id}"}
class="flex items-center justify-between rounded-lg border border-zinc-200 bg-white p-4 dark:border-zinc-800 dark:bg-zinc-900 hover:border-zinc-300 dark:hover:border-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-800 transition-colors cursor-pointer"
>
diff --git a/lib/towerops_web/router.ex b/lib/towerops_web/router.ex
index 75f70b7f..180665b7 100644
--- a/lib/towerops_web/router.ex
+++ b/lib/towerops_web/router.ex
@@ -198,6 +198,24 @@ defmodule ToweropsWeb.Router do
live "/", DashboardLive, :index
live "/settings", Org.SettingsLive, :index
+ # Alert routes
+ live "/alerts", AlertLive.Index, :index
+
+ # Agent routes
+ live "/agents", AgentLive.Index, :index
+ live "/agents/:id/edit", AgentLive.Edit, :edit
+ live "/agents/:id", AgentLive.Show, :show
+ end
+ end
+
+ live_session :require_authenticated_user_with_default_org,
+ on_mount: [
+ {ToweropsWeb.UserAuth, :require_authenticated_user},
+ {ToweropsWeb.UserAuth, :load_default_organization}
+ ] do
+ scope "/", ToweropsWeb do
+ pipe_through [:browser, :require_authenticated_user]
+
# Site routes
live "/sites", SiteLive.Index, :index
live "/sites/new", SiteLive.Form, :new
@@ -210,14 +228,6 @@ defmodule ToweropsWeb.Router do
live "/devices/:id", DeviceLive.Show, :show
live "/devices/:id/edit", DeviceLive.Form, :edit
live "/devices/:id/graph/:sensor_type", GraphLive.Show, :show
-
- # Alert routes
- live "/alerts", AlertLive.Index, :index
-
- # Agent routes
- live "/agents", AgentLive.Index, :index
- live "/agents/:id/edit", AgentLive.Edit, :edit
- live "/agents/:id", AgentLive.Show, :show
end
end
end
diff --git a/lib/towerops_web/user_auth.ex b/lib/towerops_web/user_auth.ex
index eedd1e83..49f21902 100644
--- a/lib/towerops_web/user_auth.ex
+++ b/lib/towerops_web/user_auth.ex
@@ -247,9 +247,9 @@ defmodule ToweropsWeb.UserAuth do
if user do
# Get user's organizations (ordered by most recently joined first)
case Towerops.Organizations.list_user_organizations(user.id) do
- [first_org | _] ->
- # device page
- ~p"/orgs/#{first_org.slug}/devices"
+ [_first_org | _] ->
+ # Devices page (no longer needs org slug)
+ ~p"/devices"
[] ->
# No organizations yet, go to org list
@@ -428,6 +428,57 @@ defmodule ToweropsWeb.UserAuth do
{:cont, socket}
end
+ def on_mount(:load_default_organization, _params, session, socket) do
+ user = socket.assigns.current_scope && socket.assigns.current_scope.user
+
+ if user do
+ # Try to get organization from session, otherwise use first organization
+ org_id = session["current_organization_id"]
+
+ organization =
+ if org_id do
+ try do
+ Towerops.Organizations.get_organization!(org_id)
+ rescue
+ Ecto.NoResultsError -> nil
+ end
+ else
+ # Get first organization user has access to
+ case Towerops.Organizations.list_user_organizations(user.id) do
+ [first_org | _] -> first_org
+ [] -> nil
+ end
+ end
+
+ if organization do
+ membership = Towerops.Organizations.get_membership(organization.id, user.id)
+
+ if membership do
+ {:cont,
+ socket
+ |> Phoenix.Component.assign(:current_organization, organization)
+ |> Phoenix.Component.assign(:current_membership, membership)}
+ else
+ socket =
+ socket
+ |> LiveView.put_flash(:error, "You don't have access to any organizations.")
+ |> LiveView.redirect(to: ~p"/orgs")
+
+ {:halt, socket}
+ end
+ else
+ socket =
+ socket
+ |> LiveView.put_flash(:error, "Please select an organization.")
+ |> LiveView.redirect(to: ~p"/orgs")
+
+ {:halt, socket}
+ end
+ else
+ {:cont, socket}
+ end
+ end
+
def on_mount(:require_superuser, _params, session, socket) do
socket = mount_current_scope(socket, session)
user = socket.assigns.current_scope && socket.assigns.current_scope.user
@@ -596,10 +647,10 @@ defmodule ToweropsWeb.UserAuth do
ip_address: ip
})
- # device page
+ # Devices page
redirect_path =
case Towerops.Organizations.list_user_organizations(superuser.id) do
- [first_org | _] -> ~p"/orgs/#{first_org.slug}/devices"
+ [_first_org | _] -> ~p"/devices"
[] -> ~p"/orgs"
end
|