mirror of
https://github.com/wanderer-industries/wanderer
synced 2026-08-23 22:36:45 +00:00
feat: track Save Mass (locked) status on connections
This commit is contained in:
+28
-16
@@ -196,23 +196,35 @@ export const Connections = ({ selectedConnection, onHide }: OnTheMapProps) => {
|
||||
{/* Connection Info */}
|
||||
<div className="px-2 flex flex-col gap-2">
|
||||
{/* Connection Info Row */}
|
||||
<InfoDrawer title="Connection" rightSide>
|
||||
<div className="flex justify-end gap-2 items-center">
|
||||
<SystemView
|
||||
showCustomName
|
||||
systemId={cnInfo.source}
|
||||
className={clsx(classes.InfoTextSize, 'select-none text-center')}
|
||||
hideRegion
|
||||
/>
|
||||
<span className="pi pi-angle-double-right text-stone-500 text-[15px]"></span>
|
||||
<SystemView
|
||||
showCustomName
|
||||
systemId={cnInfo.target}
|
||||
className={clsx(classes.InfoTextSize, 'select-none text-center')}
|
||||
hideRegion
|
||||
/>
|
||||
<div className="flex justify-between gap-2">
|
||||
{/*Left column*/}
|
||||
<div>
|
||||
{isWormhole && info?.locked_at && (
|
||||
<InfoDrawer title="Save Mass">
|
||||
<TimeAgo timestamp={info.locked_at} />
|
||||
{info.locked_by_name && <span className="text-neutral-400"> by {info.locked_by_name}</span>}
|
||||
</InfoDrawer>
|
||||
)}
|
||||
</div>
|
||||
</InfoDrawer>
|
||||
{/*Right column*/}
|
||||
<InfoDrawer title="Connection" rightSide>
|
||||
<div className="flex justify-end gap-2 items-center">
|
||||
<SystemView
|
||||
showCustomName
|
||||
systemId={cnInfo.source}
|
||||
className={clsx(classes.InfoTextSize, 'select-none text-center')}
|
||||
hideRegion
|
||||
/>
|
||||
<span className="pi pi-angle-double-right text-stone-500 text-[15px]"></span>
|
||||
<SystemView
|
||||
showCustomName
|
||||
systemId={cnInfo.target}
|
||||
className={clsx(classes.InfoTextSize, 'select-none text-center')}
|
||||
hideRegion
|
||||
/>
|
||||
</div>
|
||||
</InfoDrawer>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between gap-2">
|
||||
{/*Left column*/}
|
||||
|
||||
@@ -21,6 +21,8 @@ export type PassageWithSourceTarget = {
|
||||
|
||||
export type ConnectionInfoOutput = {
|
||||
marl_eol_time: string;
|
||||
locked_at: string | null;
|
||||
locked_by_name: string | null;
|
||||
};
|
||||
|
||||
export type ConnectionOutput = {
|
||||
|
||||
@@ -20,7 +20,7 @@ defmodule WandererApp.Api.MapConnection do
|
||||
json_api do
|
||||
type "map_connections"
|
||||
|
||||
includes([:map])
|
||||
includes([:map, :locked_by])
|
||||
|
||||
default_fields([
|
||||
:solar_system_source,
|
||||
@@ -32,6 +32,7 @@ defmodule WandererApp.Api.MapConnection do
|
||||
:wormhole_type,
|
||||
:count_of_passage,
|
||||
:locked,
|
||||
:locked_at,
|
||||
:custom_info
|
||||
])
|
||||
|
||||
@@ -274,6 +275,11 @@ defmodule WandererApp.Api.MapConnection do
|
||||
public? true
|
||||
end
|
||||
|
||||
attribute :locked_at, :utc_datetime_usec do
|
||||
public? true
|
||||
allow_nil? true
|
||||
end
|
||||
|
||||
attribute :custom_info, :string do
|
||||
public? true
|
||||
allow_nil? true
|
||||
@@ -288,5 +294,9 @@ defmodule WandererApp.Api.MapConnection do
|
||||
attribute_writable? true
|
||||
public? true
|
||||
end
|
||||
|
||||
belongs_to :locked_by, WandererApp.Api.Character do
|
||||
public? true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -213,9 +213,34 @@ defmodule WandererApp.Map.Server.ConnectionsImpl do
|
||||
solar_system_target_id
|
||||
)
|
||||
|> case do
|
||||
{:ok, %{id: connection_id}} ->
|
||||
{:ok, %{id: connection_id} = connection} ->
|
||||
connection_mark_eol_time = get_connection_mark_eol_time(map_id, connection_id, nil)
|
||||
{:ok, %{marl_eol_time: connection_mark_eol_time}}
|
||||
locked_info = get_connection_locked_info(map_id, connection_id)
|
||||
|
||||
locked_by_name =
|
||||
case locked_info do
|
||||
nil ->
|
||||
nil
|
||||
|
||||
%{locked_by_id: locked_by_id} ->
|
||||
case WandererApp.Api.Character.by_id(locked_by_id) do
|
||||
{:ok, character} -> character.name
|
||||
_ -> nil
|
||||
end
|
||||
end
|
||||
|
||||
locked_at =
|
||||
case locked_info do
|
||||
nil -> nil
|
||||
%{locked_at: locked_at} -> locked_at
|
||||
end
|
||||
|
||||
{:ok,
|
||||
%{
|
||||
marl_eol_time: connection_mark_eol_time,
|
||||
locked_at: locked_at,
|
||||
locked_by_name: locked_by_name
|
||||
}}
|
||||
|
||||
_ ->
|
||||
{:error, :not_found}
|
||||
@@ -293,8 +318,27 @@ defmodule WandererApp.Map.Server.ConnectionsImpl do
|
||||
def update_connection_locked(
|
||||
map_id,
|
||||
connection_update
|
||||
),
|
||||
do: update_connection(map_id, :update_locked, [:locked], connection_update)
|
||||
) do
|
||||
update_connection(map_id, :update_locked, [:locked], connection_update, fn
|
||||
%{locked: old_locked}, %{id: connection_id, locked: new_locked} = _ ->
|
||||
case new_locked do
|
||||
true ->
|
||||
if not old_locked do
|
||||
character_id = Map.get(connection_update, :character_id)
|
||||
|
||||
WandererApp.Cache.put(
|
||||
"map_#{map_id}:conn_#{connection_id}:locked_info",
|
||||
%{locked_by_id: character_id, locked_at: DateTime.utc_now()}
|
||||
)
|
||||
end
|
||||
|
||||
_ ->
|
||||
if old_locked do
|
||||
WandererApp.Cache.delete("map_#{map_id}:conn_#{connection_id}:locked_info")
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
def update_connection_custom_info(
|
||||
map_id,
|
||||
@@ -954,6 +998,16 @@ defmodule WandererApp.Map.Server.ConnectionsImpl do
|
||||
end
|
||||
end
|
||||
|
||||
def get_connection_locked_info(map_id, connection_id) do
|
||||
case WandererApp.Cache.get("map_#{map_id}:conn_#{connection_id}:locked_info") do
|
||||
nil ->
|
||||
nil
|
||||
|
||||
value ->
|
||||
value
|
||||
end
|
||||
end
|
||||
|
||||
defp find_solar_system_jump(from_solar_system_id, to_solar_system_id) do
|
||||
case WandererApp.CachedInfo.get_solar_system_jump(from_solar_system_id, to_solar_system_id) do
|
||||
{:ok, jump} when not is_nil(jump) -> {:ok, [jump]}
|
||||
@@ -1033,6 +1087,7 @@ defmodule WandererApp.Map.Server.ConnectionsImpl do
|
||||
})
|
||||
|
||||
WandererApp.Cache.delete("map_#{map_id}:conn_#{connection.id}:start_time")
|
||||
WandererApp.Cache.delete("map_#{map_id}:conn_#{connection.id}:locked_info")
|
||||
|
||||
# Clear linked_sig_eve_id on target system when connection is deleted
|
||||
# This ensures old signatures become orphaned and won't affect future connections
|
||||
|
||||
@@ -240,6 +240,7 @@ defmodule WandererAppWeb.MapConnectionsEventHandler do
|
||||
solar_system_target_id: solar_system_target_id_int
|
||||
}
|
||||
|> Map.put_new(key_atom, value)
|
||||
|> Map.put(:character_id, main_character_id)
|
||||
])
|
||||
|
||||
{:noreply, socket}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
defmodule WandererApp.Repo.Migrations.AddMapConnectionLockedBy do
|
||||
@moduledoc """
|
||||
Add locked_by and locked_at tracking to map_chain_v1 connections
|
||||
"""
|
||||
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
alter table(:map_chain_v1) do
|
||||
add :locked_by_id, :binary_id
|
||||
add :locked_at, :utc_datetime_usec
|
||||
end
|
||||
end
|
||||
|
||||
def down do
|
||||
alter table(:map_chain_v1) do
|
||||
remove :locked_by_id
|
||||
remove :locked_at
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user