Add active page navigation highlighting
- Add active_page attribute to authenticated layout - Update nav_link component to show active state with border and text styling - Update all LiveView templates to pass active_page parameter - Fix datetime truncation issues in tests and schemas for :utc_datetime fields - Fix dashboard test assertions for equipment status text
This commit is contained in:
parent
d283f4ac6c
commit
7d4f7dd7d4
11 changed files with 77 additions and 26 deletions
|
|
@ -204,7 +204,10 @@ defmodule Towerops.Organizations do
|
|||
def accept_invitation(invitation, user_id) do
|
||||
Ecto.Multi.new()
|
||||
|> Ecto.Multi.update(:invitation, fn _ ->
|
||||
Ecto.Changeset.change(invitation, %{accepted_at: DateTime.utc_now(), accepted_by_id: user_id})
|
||||
Ecto.Changeset.change(invitation, %{
|
||||
accepted_at: DateTime.truncate(DateTime.utc_now(), :second),
|
||||
accepted_by_id: user_id
|
||||
})
|
||||
end)
|
||||
|> Ecto.Multi.insert(:membership, fn _ ->
|
||||
Membership.changeset(%Membership{}, %{
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ defmodule Towerops.Organizations.Invitation do
|
|||
end
|
||||
|
||||
defp set_expires_at(changeset) do
|
||||
expires_at = DateTime.add(DateTime.utc_now(), 7, :day)
|
||||
expires_at = DateTime.utc_now() |> DateTime.add(7, :day) |> DateTime.truncate(:second)
|
||||
put_change(changeset, :expires_at, expires_at)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ defmodule ToweropsWeb.Layouts do
|
|||
|
||||
## Examples
|
||||
|
||||
<Layouts.authenticated flash={@flash} current_organization={@current_organization}>
|
||||
<Layouts.authenticated flash={@flash} current_organization={@current_organization} active_page="dashboard">
|
||||
<h1>Content</h1>
|
||||
</Layouts.authenticated>
|
||||
|
||||
|
|
@ -63,6 +63,10 @@ defmodule ToweropsWeb.Layouts do
|
|||
default: nil,
|
||||
doc: "the current organization"
|
||||
|
||||
attr :active_page, :string,
|
||||
default: nil,
|
||||
doc: "the currently active page (dashboard, sites, equipment, or alerts)"
|
||||
|
||||
slot :inner_block, required: true
|
||||
|
||||
def authenticated(assigns) do
|
||||
|
|
@ -78,16 +82,28 @@ defmodule ToweropsWeb.Layouts do
|
|||
</.link>
|
||||
</div>
|
||||
<div :if={@current_organization} class="ml-10 flex space-x-8">
|
||||
<.nav_link navigate={~p"/orgs/#{@current_organization.slug}"}>
|
||||
<.nav_link
|
||||
navigate={~p"/orgs/#{@current_organization.slug}"}
|
||||
active={@active_page == "dashboard"}
|
||||
>
|
||||
Dashboard
|
||||
</.nav_link>
|
||||
<.nav_link navigate={~p"/orgs/#{@current_organization.slug}/sites"}>
|
||||
<.nav_link
|
||||
navigate={~p"/orgs/#{@current_organization.slug}/sites"}
|
||||
active={@active_page == "sites"}
|
||||
>
|
||||
Sites
|
||||
</.nav_link>
|
||||
<.nav_link navigate={~p"/orgs/#{@current_organization.slug}/equipment"}>
|
||||
<.nav_link
|
||||
navigate={~p"/orgs/#{@current_organization.slug}/equipment"}
|
||||
active={@active_page == "equipment"}
|
||||
>
|
||||
Equipment
|
||||
</.nav_link>
|
||||
<.nav_link navigate={~p"/orgs/#{@current_organization.slug}/alerts"}>
|
||||
<.nav_link
|
||||
navigate={~p"/orgs/#{@current_organization.slug}/alerts"}
|
||||
active={@active_page == "alerts"}
|
||||
>
|
||||
Alerts
|
||||
</.nav_link>
|
||||
</div>
|
||||
|
|
@ -149,13 +165,21 @@ defmodule ToweropsWeb.Layouts do
|
|||
end
|
||||
|
||||
attr :navigate, :string, required: true
|
||||
attr :active, :boolean, default: false
|
||||
slot :inner_block, required: true
|
||||
|
||||
defp nav_link(assigns) do
|
||||
~H"""
|
||||
<.link
|
||||
navigate={@navigate}
|
||||
class="inline-flex items-center border-b-2 border-transparent px-1 pt-1 text-sm font-medium text-zinc-700 hover:border-zinc-300 hover:text-zinc-900 dark:text-zinc-300 dark:hover:border-zinc-700 dark:hover:text-zinc-100"
|
||||
class={[
|
||||
"inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium",
|
||||
if(@active,
|
||||
do: "border-zinc-900 text-zinc-900 dark:border-zinc-100 dark:text-zinc-100",
|
||||
else:
|
||||
"border-transparent text-zinc-700 hover:border-zinc-300 hover:text-zinc-900 dark:text-zinc-300 dark:hover:border-zinc-700 dark:hover:text-zinc-100"
|
||||
)
|
||||
]}
|
||||
>
|
||||
{render_slot(@inner_block)}
|
||||
</.link>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
<Layouts.authenticated flash={@flash} current_organization={@current_organization}>
|
||||
<Layouts.authenticated
|
||||
flash={@flash}
|
||||
current_organization={@current_organization}
|
||||
active_page="alerts"
|
||||
>
|
||||
<.header>
|
||||
Alerts
|
||||
<:subtitle>Monitor and acknowledge system alerts</:subtitle>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
<Layouts.authenticated flash={@flash} current_organization={@current_organization}>
|
||||
<Layouts.authenticated
|
||||
flash={@flash}
|
||||
current_organization={@current_organization}
|
||||
active_page="dashboard"
|
||||
>
|
||||
<.header>
|
||||
Dashboard
|
||||
<:subtitle>Welcome to {@current_organization.name}</:subtitle>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
<Layouts.authenticated flash={@flash} current_organization={@current_organization}>
|
||||
<Layouts.authenticated
|
||||
flash={@flash}
|
||||
current_organization={@current_organization}
|
||||
active_page="equipment"
|
||||
>
|
||||
<.header>
|
||||
{@page_title}
|
||||
<:subtitle>Monitor and manage all your network equipment</:subtitle>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
<Layouts.authenticated flash={@flash} current_organization={@current_organization}>
|
||||
<Layouts.authenticated
|
||||
flash={@flash}
|
||||
current_organization={@current_organization}
|
||||
active_page="equipment"
|
||||
>
|
||||
<.header>
|
||||
{@page_title}
|
||||
<:subtitle>{@equipment.ip_address}</:subtitle>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
<Layouts.authenticated flash={@flash} current_organization={@current_organization}>
|
||||
<Layouts.authenticated
|
||||
flash={@flash}
|
||||
current_organization={@current_organization}
|
||||
active_page="sites"
|
||||
>
|
||||
<.header>
|
||||
{@page_title}
|
||||
<:subtitle>Manage your site locations and hierarchy</:subtitle>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
<Layouts.authenticated flash={@flash} current_organization={@current_organization}>
|
||||
<Layouts.authenticated
|
||||
flash={@flash}
|
||||
current_organization={@current_organization}
|
||||
active_page="sites"
|
||||
>
|
||||
<.header>
|
||||
{@page_title}
|
||||
<:subtitle>{@site.location}</:subtitle>
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ defmodule Towerops.OrganizationsTest do
|
|||
role: :member,
|
||||
invited_by_id: owner.id,
|
||||
token: "test-token-#{System.unique_integer()}",
|
||||
expires_at: DateTime.add(DateTime.utc_now(), 7, :day)
|
||||
expires_at: DateTime.truncate(DateTime.add(DateTime.utc_now(), 7, :day), :second)
|
||||
})
|
||||
|
||||
invitations = Organizations.list_pending_invitations(organization.id)
|
||||
|
|
@ -244,8 +244,8 @@ defmodule Towerops.OrganizationsTest do
|
|||
role: :member,
|
||||
invited_by_id: owner.id,
|
||||
token: "test-token-#{System.unique_integer()}",
|
||||
expires_at: DateTime.add(DateTime.utc_now(), 7, :day),
|
||||
accepted_at: DateTime.utc_now()
|
||||
expires_at: DateTime.truncate(DateTime.add(DateTime.utc_now(), 7, :day), :second),
|
||||
accepted_at: DateTime.truncate(DateTime.utc_now(), :second)
|
||||
})
|
||||
|
||||
invitations = Organizations.list_pending_invitations(organization.id)
|
||||
|
|
@ -263,7 +263,7 @@ defmodule Towerops.OrganizationsTest do
|
|||
role: :member,
|
||||
invited_by_id: owner.id,
|
||||
token: "test-token-#{System.unique_integer()}",
|
||||
expires_at: DateTime.add(DateTime.utc_now(), -1, :day)
|
||||
expires_at: DateTime.truncate(DateTime.add(DateTime.utc_now(), -1, :day), :second)
|
||||
})
|
||||
|
||||
invitations = Organizations.list_pending_invitations(organization.id)
|
||||
|
|
@ -280,7 +280,7 @@ defmodule Towerops.OrganizationsTest do
|
|||
role: :member,
|
||||
invited_by_id: owner.id,
|
||||
token: "unique-token-#{System.unique_integer()}",
|
||||
expires_at: DateTime.add(DateTime.utc_now(), 7, :day)
|
||||
expires_at: DateTime.truncate(DateTime.add(DateTime.utc_now(), 7, :day), :second)
|
||||
}
|
||||
|
||||
assert {:ok, invitation} = Organizations.create_invitation(valid_attrs)
|
||||
|
|
@ -301,7 +301,7 @@ defmodule Towerops.OrganizationsTest do
|
|||
role: :member,
|
||||
invited_by_id: owner.id,
|
||||
token: token,
|
||||
expires_at: DateTime.add(DateTime.utc_now(), 7, :day)
|
||||
expires_at: DateTime.truncate(DateTime.add(DateTime.utc_now(), 7, :day), :second)
|
||||
})
|
||||
|
||||
invitation = Organizations.get_invitation_by_token(token)
|
||||
|
|
@ -321,8 +321,8 @@ defmodule Towerops.OrganizationsTest do
|
|||
role: :member,
|
||||
invited_by_id: owner.id,
|
||||
token: token,
|
||||
expires_at: DateTime.add(DateTime.utc_now(), 7, :day),
|
||||
accepted_at: DateTime.utc_now()
|
||||
expires_at: DateTime.truncate(DateTime.add(DateTime.utc_now(), 7, :day), :second),
|
||||
accepted_at: DateTime.truncate(DateTime.utc_now(), :second)
|
||||
})
|
||||
|
||||
assert Organizations.get_invitation_by_token(token) == nil
|
||||
|
|
@ -341,7 +341,7 @@ defmodule Towerops.OrganizationsTest do
|
|||
role: :member,
|
||||
invited_by_id: owner.id,
|
||||
token: token,
|
||||
expires_at: DateTime.add(DateTime.utc_now(), 7, :day)
|
||||
expires_at: DateTime.truncate(DateTime.add(DateTime.utc_now(), 7, :day), :second)
|
||||
})
|
||||
|
||||
new_user = user_fixture()
|
||||
|
|
@ -364,7 +364,7 @@ defmodule Towerops.OrganizationsTest do
|
|||
role: :member,
|
||||
invited_by_id: owner.id,
|
||||
token: "test-token-#{System.unique_integer()}",
|
||||
expires_at: DateTime.add(DateTime.utc_now(), 7, :day)
|
||||
expires_at: DateTime.truncate(DateTime.add(DateTime.utc_now(), 7, :day), :second)
|
||||
})
|
||||
|
||||
assert {:ok, _} = Organizations.delete_invitation(invitation)
|
||||
|
|
|
|||
|
|
@ -63,8 +63,8 @@ defmodule ToweropsWeb.DashboardLiveTest do
|
|||
|
||||
{:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}")
|
||||
assert html =~ "Equipment"
|
||||
assert html =~ "UP"
|
||||
assert html =~ "DOWN"
|
||||
assert html =~ "Up"
|
||||
assert html =~ "Down"
|
||||
end
|
||||
|
||||
test "displays active alerts count", %{conn: conn, organization: organization, site: site} do
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue