mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
refactor(portal): Use popover with UTC timestamp for datetime fields (#5712)
Fixes #5249 to allow copy-pasting the timestamp Fixes #5635 by virtue of using a relative datetime there. Fixes #5225 <img width="579" alt="Screenshot 2024-07-03 at 10 58 11 PM" src="https://github.com/firezone/firezone/assets/167144/261a5f58-ab9c-40b3-a26f-3adcff228aa9">
This commit is contained in:
@@ -771,19 +771,53 @@ defmodule Web.CoreComponents do
|
||||
assigns = assign_new(assigns, :relative_to, fn -> DateTime.utc_now() end)
|
||||
|
||||
~H"""
|
||||
<span
|
||||
:if={not is_nil(@datetime)}
|
||||
class="underline underline-offset-2 decoration-dotted"
|
||||
title={@datetime}
|
||||
>
|
||||
<%= Cldr.DateTime.Relative.to_string!(@datetime, Web.CLDR, relative_to: @relative_to) %>
|
||||
</span>
|
||||
<.popover :if={not is_nil(@datetime)}>
|
||||
<:target>
|
||||
<span class="underline underline-offset-2 decoration-dashed">
|
||||
<%= Cldr.DateTime.Relative.to_string!(@datetime, Web.CLDR, relative_to: @relative_to)
|
||||
|> String.capitalize() %>
|
||||
</span>
|
||||
</:target>
|
||||
<:content>
|
||||
<%= @datetime %>
|
||||
</:content>
|
||||
</.popover>
|
||||
<span :if={is_nil(@datetime)}>
|
||||
never
|
||||
Never
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
||||
@doc """
|
||||
Renders a popover element with title and content.
|
||||
"""
|
||||
slot :target, required: true
|
||||
slot :content, required: true
|
||||
|
||||
def popover(assigns) do
|
||||
# Any id will do
|
||||
target_id = "popover-#{System.unique_integer([:positive, :monotonic])}"
|
||||
assigns = assign(assigns, :target_id, target_id)
|
||||
|
||||
~H"""
|
||||
<span data-popover-target={@target_id}>
|
||||
<%= render_slot(@target) %>
|
||||
</span>
|
||||
|
||||
<div data-popover id={@target_id} role="tooltip" class={~w[
|
||||
absolute z-10 invisible inline-block
|
||||
text-sm text-neutral-500 transition-opacity
|
||||
duration-50 bg-white border border-neutral-200
|
||||
rounded shadow-sm opacity-0
|
||||
]}>
|
||||
<div class="px-3 py-2">
|
||||
<%= render_slot(@content) %>
|
||||
</div>
|
||||
<div data-popper-arrow></div>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
@doc """
|
||||
Renders online or offline status using an `online?` field of the schema.
|
||||
"""
|
||||
|
||||
@@ -150,13 +150,7 @@ defmodule Web.Policies.Show do
|
||||
Created
|
||||
</:label>
|
||||
<:value>
|
||||
<.datetime datetime={@policy.inserted_at} /> by
|
||||
<.link
|
||||
navigate={~p"/#{@account}/actors/#{@policy.created_by_identity.actor.id}"}
|
||||
class={link_style()}
|
||||
>
|
||||
<%= @policy.created_by_identity.actor.name %>
|
||||
</.link>
|
||||
<.created_by account={@account} schema={@policy} />
|
||||
</:value>
|
||||
</.vertical_table_row>
|
||||
</.vertical_table>
|
||||
|
||||
@@ -202,7 +202,7 @@ defmodule Web.ConnCase do
|
||||
### Helpers to test formatted time units
|
||||
|
||||
def around_now?(string) do
|
||||
if string =~ "now" do
|
||||
if string =~ "Now" do
|
||||
true
|
||||
else
|
||||
[_all, seconds] = Regex.run(~r/([0-9]+) second[s]? ago/, string)
|
||||
|
||||
@@ -99,7 +99,7 @@ defmodule Web.Live.Actors.IndexTest do
|
||||
assert row["groups"] =~ group.name
|
||||
end
|
||||
|
||||
assert row["last signed in"] == "never"
|
||||
assert row["last signed in"] == "Never"
|
||||
end)
|
||||
end
|
||||
end
|
||||
@@ -133,7 +133,7 @@ defmodule Web.Live.Actors.IndexTest do
|
||||
|> render()
|
||||
|> table_to_map()
|
||||
|> with_table_row("name", actor.name, fn row ->
|
||||
assert row["last signed in"] == "1 hour ago"
|
||||
assert String.contains?(row["last signed in"], "1 hour ago")
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -359,7 +359,7 @@ defmodule Web.Live.Actors.ShowTest do
|
||||
fn row ->
|
||||
assert row["actions"] =~ "Delete"
|
||||
assert row["created"] =~ "by #{actor.name}"
|
||||
assert row["last signed in"] == "never"
|
||||
assert row["last signed in"] == "Never"
|
||||
end
|
||||
)
|
||||
|> with_table_row(
|
||||
@@ -368,7 +368,7 @@ defmodule Web.Live.Actors.ShowTest do
|
||||
fn row ->
|
||||
refute row["actions"]
|
||||
assert row["created"] =~ "by #{synced_identity.provider.name} sync"
|
||||
assert row["last signed in"] == "never"
|
||||
assert row["last signed in"] == "Never"
|
||||
end
|
||||
)
|
||||
end
|
||||
@@ -661,14 +661,20 @@ defmodule Web.Live.Actors.ShowTest do
|
||||
|> table_to_map()
|
||||
|
||||
assert row1["type"] == "browser"
|
||||
assert row1["expires"] in ["tomorrow", "in 24 hours"]
|
||||
assert row1["last used"] == "never"
|
||||
|
||||
assert String.contains?(row1["expires"], "Tomorrow") ||
|
||||
String.contains?(row1["expires"], "In 24 hours")
|
||||
|
||||
assert row1["last used"] == "Never"
|
||||
assert around_now?(row1["created"])
|
||||
assert row1["actions"] == "Revoke"
|
||||
|
||||
assert row2["type"] == "client"
|
||||
assert row2["expires"] in ["tomorrow", "in 24 hours"]
|
||||
assert row2["last used"] == "never"
|
||||
|
||||
assert String.contains?(row2["expires"], "Tomorrow") ||
|
||||
String.contains?(row2["expires"], "In 24 hours")
|
||||
|
||||
assert row2["last used"] == "Never"
|
||||
assert around_now?(row2["created"])
|
||||
assert row2["actions"] == "Revoke"
|
||||
end
|
||||
@@ -928,7 +934,7 @@ defmodule Web.Live.Actors.ShowTest do
|
||||
|> element("#actor")
|
||||
|> render()
|
||||
|> vertical_table_to_map() == %{
|
||||
"last signed in" => "never",
|
||||
"last signed in" => "Never",
|
||||
"name" => actor.name,
|
||||
"role" => "service account"
|
||||
}
|
||||
@@ -1084,14 +1090,20 @@ defmodule Web.Live.Actors.ShowTest do
|
||||
|> table_to_map()
|
||||
|
||||
assert row1["type"] == "browser"
|
||||
assert row1["expires"] in ["tomorrow", "in 24 hours"]
|
||||
assert row1["last used"] == "never"
|
||||
|
||||
assert String.contains?(row1["expires"], "Tomorrow") ||
|
||||
String.contains?(row1["expires"], "In 24 hours")
|
||||
|
||||
assert row1["last used"] == "Never"
|
||||
assert around_now?(row1["created"])
|
||||
assert row1["actions"] == "Revoke"
|
||||
|
||||
assert row2["type"] == "client"
|
||||
assert row2["expires"] in ["tomorrow", "in 24 hours"]
|
||||
assert row2["last used"] == "never"
|
||||
|
||||
assert String.contains?(row2["expires"], "Tomorrow") ||
|
||||
String.contains?(row2["expires"], "In 24 hours")
|
||||
|
||||
assert row2["last used"] == "Never"
|
||||
assert around_now?(row2["created"])
|
||||
assert row2["actions"] == "Revoke"
|
||||
end
|
||||
|
||||
@@ -214,7 +214,7 @@ defmodule Web.Live.Settings.ApiClients.ShowTest do
|
||||
|
||||
assert row1["name"] == token.name
|
||||
assert row1["expires at"]
|
||||
assert row1["last used"] == "never"
|
||||
assert row1["last used"] == "Never"
|
||||
assert row1["actions"] == "Revoke"
|
||||
end
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ defmodule Web.Live.Settings.IdentityProviders.IndexTest do
|
||||
|> render()
|
||||
|> table_to_map()
|
||||
|> with_table_row("name", provider.name, fn row ->
|
||||
assert row["sync status"] == "Synced 2 identities and 1 group 1 hour ago"
|
||||
assert String.contains?(row["sync status"], "Synced 2 identities and 1 group 1 hour ago")
|
||||
end)
|
||||
|
||||
provider =
|
||||
|
||||
Reference in New Issue
Block a user