mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-11-29 12:33:22 +00:00
Compare commits
1 Commits
fix-error-
...
connection
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6fa088e4d |
@@ -1,13 +1,20 @@
|
||||
import classes from './Connections.module.scss';
|
||||
import { Sidebar } from 'primereact/sidebar';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useEffect, useMemo, useState, useCallback } from 'react';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { VirtualScroller, VirtualScrollerTemplateOptions } from 'primereact/virtualscroller';
|
||||
import clsx from 'clsx';
|
||||
import { ConnectionOutput, OutCommand, Passage, SolarSystemConnection } from '@/hooks/Mapper/types';
|
||||
import {
|
||||
ConnectionOutput,
|
||||
ConnectionInfoOutput,
|
||||
OutCommand,
|
||||
Passage,
|
||||
SolarSystemConnection,
|
||||
} from '@/hooks/Mapper/types';
|
||||
import { PassageCard } from './PassageCard';
|
||||
import { InfoDrawer, SystemView } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { kgToTons } from '@/hooks/Mapper/utils/kgToTons.ts';
|
||||
import { TimeAgo } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
const sortByDate = (a: string, b: string) => new Date(a).getTime() - new Date(b).getTime();
|
||||
|
||||
@@ -69,25 +76,44 @@ export const Connections = ({ selectedConnection, onHide }: OnTheMapProps) => {
|
||||
}, [connections, selectedConnection]);
|
||||
|
||||
const [passages, setPassages] = useState<Passage[]>([]);
|
||||
const [info, setInfo] = useState<ConnectionInfoOutput>(null);
|
||||
|
||||
const loadInfo = useCallback(
|
||||
async (connection: SolarSystemConnection) => {
|
||||
const result = await outCommand<ConnectionInfoOutput>({
|
||||
type: OutCommand.getConnectionInfo,
|
||||
data: {
|
||||
from: connection.source,
|
||||
to: connection.target,
|
||||
},
|
||||
});
|
||||
|
||||
setInfo(result);
|
||||
},
|
||||
[outCommand],
|
||||
);
|
||||
|
||||
const loadPassages = useCallback(
|
||||
async (connection: SolarSystemConnection) => {
|
||||
const result = await outCommand<ConnectionOutput>({
|
||||
type: OutCommand.getPassages,
|
||||
data: {
|
||||
from: connection.source,
|
||||
to: connection.target,
|
||||
},
|
||||
});
|
||||
|
||||
setPassages(result.passages.sort((a, b) => sortByDate(b.inserted_at, a.inserted_at)));
|
||||
},
|
||||
[outCommand],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectedConnection) {
|
||||
return;
|
||||
}
|
||||
|
||||
const loadInfo = async () => {
|
||||
const result = await outCommand<ConnectionOutput>({
|
||||
type: OutCommand.getPassages,
|
||||
data: {
|
||||
from: selectedConnection.source,
|
||||
to: selectedConnection.target,
|
||||
},
|
||||
});
|
||||
|
||||
setPassages(result.passages.sort((a, b) => sortByDate(b.inserted_at, a.inserted_at)));
|
||||
};
|
||||
|
||||
loadInfo();
|
||||
loadInfo(selectedConnection);
|
||||
loadPassages(selectedConnection);
|
||||
}, [selectedConnection]);
|
||||
|
||||
const approximateMass = useMemo(() => {
|
||||
@@ -132,6 +158,10 @@ export const Connections = ({ selectedConnection, onHide }: OnTheMapProps) => {
|
||||
{kgToTons(approximateMass)}
|
||||
</InfoDrawer>
|
||||
|
||||
<InfoDrawer title="Mark EOL Time" rightSide>
|
||||
{info?.marl_eol_time ? <TimeAgo timestamp={info.marl_eol_time} /> : ' unknown '}
|
||||
</InfoDrawer>
|
||||
|
||||
<div className="flex gap-2"></div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -11,6 +11,10 @@ export type Passage = {
|
||||
character: PassageLimitedCharacterType;
|
||||
};
|
||||
|
||||
export type ConnectionInfoOutput = {
|
||||
marl_eol_time: string;
|
||||
};
|
||||
|
||||
export type ConnectionOutput = {
|
||||
passages: Passage[];
|
||||
};
|
||||
|
||||
@@ -118,6 +118,7 @@ export enum OutCommand {
|
||||
getCharacterJumps = 'get_character_jumps',
|
||||
getSignatures = 'get_signatures',
|
||||
getSystemStaticInfos = 'get_system_static_infos',
|
||||
getConnectionInfo = 'get_connection_info',
|
||||
updateConnectionTimeStatus = 'update_connection_time_status',
|
||||
updateConnectionMassStatus = 'update_connection_mass_status',
|
||||
updateConnectionShipSizeType = 'update_connection_ship_size_type',
|
||||
|
||||
@@ -183,6 +183,12 @@ defmodule WandererApp.Map.Server do
|
||||
|> map_pid!
|
||||
|> GenServer.cast({&Impl.delete_connection/2, [connection_info]})
|
||||
|
||||
def get_connection_info(map_id, connection_info) when is_binary(map_id),
|
||||
do:
|
||||
map_id
|
||||
|> map_pid!
|
||||
|> GenServer.call({&Impl.get_connection_info/2, [connection_info]}, :timer.minutes(1))
|
||||
|
||||
def update_connection_time_status(map_id, connection_info) when is_binary(map_id),
|
||||
do:
|
||||
map_id
|
||||
|
||||
@@ -153,8 +153,8 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
Process.send_after(self(), :update_tracked_characters, 100)
|
||||
Process.send_after(self(), :update_presence, @update_presence_timeout)
|
||||
Process.send_after(self(), :cleanup_connections, 5000)
|
||||
Process.send_after(self(), :cleanup_systems, 10000)
|
||||
Process.send_after(self(), :cleanup_characters, @characters_cleanup_timeout)
|
||||
Process.send_after(self(), :cleanup_systems, 10_000)
|
||||
Process.send_after(self(), :cleanup_characters, :timer.minutes(5))
|
||||
Process.send_after(self(), :backup_state, @backup_state_timeout)
|
||||
|
||||
WandererApp.Cache.insert("map_#{map_id}:started", true)
|
||||
@@ -259,37 +259,37 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
state,
|
||||
update
|
||||
),
|
||||
do: state |> _update_system(:update_name, [:name], update)
|
||||
do: state |> update_system(:update_name, [:name], update)
|
||||
|
||||
def update_system_description(
|
||||
state,
|
||||
update
|
||||
),
|
||||
do: state |> _update_system(:update_description, [:description], update)
|
||||
do: state |> update_system(:update_description, [:description], update)
|
||||
|
||||
def update_system_status(
|
||||
state,
|
||||
update
|
||||
),
|
||||
do: state |> _update_system(:update_status, [:status], update)
|
||||
do: state |> update_system(:update_status, [:status], update)
|
||||
|
||||
def update_system_tag(
|
||||
state,
|
||||
update
|
||||
),
|
||||
do: state |> _update_system(:update_tag, [:tag], update)
|
||||
do: state |> update_system(:update_tag, [:tag], update)
|
||||
|
||||
def update_system_locked(
|
||||
state,
|
||||
update
|
||||
),
|
||||
do: state |> _update_system(:update_locked, [:locked], update)
|
||||
do: state |> update_system(:update_locked, [:locked], update)
|
||||
|
||||
def update_system_labels(
|
||||
state,
|
||||
update
|
||||
),
|
||||
do: state |> _update_system(:update_labels, [:labels], update)
|
||||
do: state |> update_system(:update_labels, [:labels], update)
|
||||
|
||||
def update_system_position(
|
||||
%{rtree_name: rtree_name} = state,
|
||||
@@ -297,7 +297,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
),
|
||||
do:
|
||||
state
|
||||
|> _update_system(
|
||||
|> update_system(
|
||||
:update_position,
|
||||
[:position_x, :position_y],
|
||||
update,
|
||||
@@ -445,12 +445,34 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
state
|
||||
end
|
||||
|
||||
def get_connection_info(
|
||||
%{map_id: map_id} = _state,
|
||||
%{
|
||||
solar_system_source_id: solar_system_source_id,
|
||||
solar_system_target_id: solar_system_target_id
|
||||
} = _connection_info
|
||||
) do
|
||||
WandererApp.Map.find_connection(
|
||||
map_id,
|
||||
solar_system_source_id,
|
||||
solar_system_target_id
|
||||
)
|
||||
|> case do
|
||||
{:ok, %{id: connection_id}} ->
|
||||
connection_mark_eol_time = get_connection_mark_eol_time(map_id, connection_id, nil)
|
||||
{:ok, %{marl_eol_time: connection_mark_eol_time}}
|
||||
|
||||
_ ->
|
||||
{:error, :not_found}
|
||||
end
|
||||
end
|
||||
|
||||
def update_connection_time_status(
|
||||
%{map_id: map_id} = state,
|
||||
connection_update
|
||||
),
|
||||
do:
|
||||
_update_connection(state, :update_time_status, [:time_status], connection_update, fn
|
||||
update_connection(state, :update_time_status, [:time_status], connection_update, fn
|
||||
%{id: connection_id, time_status: time_status} ->
|
||||
case time_status == @connection_time_status_eol do
|
||||
true ->
|
||||
@@ -469,25 +491,25 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
state,
|
||||
connection_update
|
||||
),
|
||||
do: _update_connection(state, :update_mass_status, [:mass_status], connection_update)
|
||||
do: update_connection(state, :update_mass_status, [:mass_status], connection_update)
|
||||
|
||||
def update_connection_ship_size_type(
|
||||
state,
|
||||
connection_update
|
||||
),
|
||||
do: _update_connection(state, :update_ship_size_type, [:ship_size_type], connection_update)
|
||||
do: update_connection(state, :update_ship_size_type, [:ship_size_type], connection_update)
|
||||
|
||||
def update_connection_locked(
|
||||
state,
|
||||
connection_update
|
||||
),
|
||||
do: _update_connection(state, :update_locked, [:locked], connection_update)
|
||||
do: update_connection(state, :update_locked, [:locked], connection_update)
|
||||
|
||||
def update_connection_custom_info(
|
||||
state,
|
||||
connection_update
|
||||
),
|
||||
do: _update_connection(state, :update_custom_info, [:custom_info], connection_update)
|
||||
do: update_connection(state, :update_custom_info, [:custom_info], connection_update)
|
||||
|
||||
def import_settings(%{map_id: map_id} = state, settings, user_id) do
|
||||
WandererApp.Cache.put(
|
||||
@@ -497,9 +519,9 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
|
||||
state =
|
||||
state
|
||||
|> _maybe_import_systems(settings, user_id, nil)
|
||||
|> _maybe_import_connections(settings, user_id)
|
||||
|> _maybe_import_hubs(settings, user_id)
|
||||
|> maybe_import_systems(settings, user_id, nil)
|
||||
|> maybe_import_connections(settings, user_id)
|
||||
|> maybe_import_hubs(settings, user_id)
|
||||
|
||||
WandererApp.Cache.take("map_#{map_id}:importing")
|
||||
|
||||
@@ -531,7 +553,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
update
|
||||
|> case do
|
||||
{:character_location, location_info, old_location_info} ->
|
||||
_update_location(
|
||||
update_location(
|
||||
character_id,
|
||||
location_info,
|
||||
old_location_info,
|
||||
@@ -616,14 +638,14 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
def handle_event(:update_presence, %{map_id: map_id} = state) do
|
||||
Process.send_after(self(), :update_presence, @update_presence_timeout)
|
||||
|
||||
_update_presence(map_id)
|
||||
update_presence(map_id)
|
||||
|
||||
state
|
||||
end
|
||||
|
||||
def handle_event(:backup_state, state) do
|
||||
Process.send_after(self(), :backup_state, @backup_state_timeout)
|
||||
{:ok, _map_state} = state |> _save_map_state()
|
||||
{:ok, _map_state} = state |> save_map_state()
|
||||
|
||||
state
|
||||
end
|
||||
@@ -950,7 +972,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
end
|
||||
|
||||
def broadcast!(map_id, event, payload \\ nil) do
|
||||
if _can_broadcast?(map_id) do
|
||||
if can_broadcast?(map_id) do
|
||||
@pubsub_client.broadcast!(WandererApp.PubSub, map_id, %{event: event, payload: payload})
|
||||
end
|
||||
|
||||
@@ -977,23 +999,23 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
end
|
||||
end
|
||||
|
||||
defp get_connection_mark_eol_time(map_id, connection_id) do
|
||||
defp get_connection_mark_eol_time(map_id, connection_id, default \\ DateTime.utc_now()) do
|
||||
WandererApp.Cache.get("map_#{map_id}:conn_#{connection_id}:mark_eol_time")
|
||||
|> case do
|
||||
nil ->
|
||||
DateTime.utc_now()
|
||||
default
|
||||
|
||||
value ->
|
||||
value
|
||||
end
|
||||
end
|
||||
|
||||
defp _can_broadcast?(map_id),
|
||||
defp can_broadcast?(map_id),
|
||||
do:
|
||||
not WandererApp.Cache.lookup!("map_#{map_id}:importing", false) and
|
||||
WandererApp.Cache.lookup!("map_#{map_id}:started", false)
|
||||
|
||||
defp _update_location(
|
||||
defp update_location(
|
||||
character_id,
|
||||
location,
|
||||
old_location,
|
||||
@@ -1176,7 +1198,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
end
|
||||
end
|
||||
|
||||
defp _update_connection(
|
||||
defp update_connection(
|
||||
%{map_id: map_id} = state,
|
||||
update_method,
|
||||
attributes,
|
||||
@@ -1192,7 +1214,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
solar_system_source_id,
|
||||
solar_system_target_id
|
||||
),
|
||||
{:ok, update_map} <- _get_update_map(update, attributes),
|
||||
{:ok, update_map} <- get_update_map(update, attributes),
|
||||
:ok <-
|
||||
WandererApp.Map.update_connection(
|
||||
map_id,
|
||||
@@ -1218,7 +1240,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
end
|
||||
end
|
||||
|
||||
defp _update_system(
|
||||
defp update_system(
|
||||
%{map_id: map_id} = state,
|
||||
update_method,
|
||||
attributes,
|
||||
@@ -1231,7 +1253,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
map_id,
|
||||
update.solar_system_id
|
||||
),
|
||||
{:ok, update_map} <- _get_update_map(update, attributes) do
|
||||
{:ok, update_map} <- get_update_map(update, attributes) do
|
||||
{:ok, updated_system} =
|
||||
apply(WandererApp.MapSystemRepo, update_method, [
|
||||
system,
|
||||
@@ -1242,7 +1264,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
callback_fn.(updated_system)
|
||||
end
|
||||
|
||||
_update_map_system_last_activity(map_id, updated_system)
|
||||
update_map_system_last_activity(map_id, updated_system)
|
||||
|
||||
state
|
||||
else
|
||||
@@ -1252,7 +1274,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
end
|
||||
end
|
||||
|
||||
defp _get_update_map(update, attributes),
|
||||
defp get_update_map(update, attributes),
|
||||
do:
|
||||
{:ok,
|
||||
Enum.reduce(attributes, Map.new(), fn attribute, map ->
|
||||
@@ -1358,7 +1380,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
state
|
||||
end
|
||||
|
||||
defp _save_map_state(%{map_id: map_id} = _state) do
|
||||
defp save_map_state(%{map_id: map_id} = _state) do
|
||||
systems_last_activity =
|
||||
map_id
|
||||
|> WandererApp.Map.list_systems!()
|
||||
@@ -1489,7 +1511,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
state
|
||||
end
|
||||
|
||||
def _maybe_import_systems(state, %{"systems" => systems} = _settings, user_id, character_id) do
|
||||
def maybe_import_systems(state, %{"systems" => systems} = _settings, user_id, character_id) do
|
||||
state =
|
||||
systems
|
||||
|> Enum.reduce(state, fn %{
|
||||
@@ -1533,7 +1555,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
|> delete_systems(removed_system_ids, user_id, character_id)
|
||||
end
|
||||
|
||||
def _maybe_import_connections(state, %{"connections" => connections} = _settings, _user_id) do
|
||||
def maybe_import_connections(state, %{"connections" => connections} = _settings, _user_id) do
|
||||
connections
|
||||
|> Enum.reduce(state, fn %{
|
||||
"source" => source,
|
||||
@@ -1569,7 +1591,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
end)
|
||||
end
|
||||
|
||||
def _maybe_import_hubs(state, %{"hubs" => hubs} = _settings, _user_id) do
|
||||
def maybe_import_hubs(state, %{"hubs" => hubs} = _settings, _user_id) do
|
||||
hubs
|
||||
|> Enum.reduce(state, fn hub, acc ->
|
||||
solar_system_id = hub |> String.to_integer()
|
||||
@@ -1579,7 +1601,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
end)
|
||||
end
|
||||
|
||||
defp _update_map_system_last_activity(
|
||||
defp update_map_system_last_activity(
|
||||
map_id,
|
||||
updated_system
|
||||
) do
|
||||
@@ -1673,7 +1695,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
end
|
||||
end
|
||||
|
||||
defp _update_presence(map_id) do
|
||||
defp update_presence(map_id) do
|
||||
case WandererApp.Cache.lookup!("map_#{map_id}:started", false) and
|
||||
WandererApp.Cache.get_and_remove!("map_#{map_id}:presence_updated", false) do
|
||||
true ->
|
||||
@@ -1727,15 +1749,15 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
track_characters(rest, map_id)
|
||||
end
|
||||
|
||||
defp track_character(character_id, map_id) do
|
||||
WandererApp.Character.TrackerManager.update_track_settings(character_id, %{
|
||||
map_id: map_id,
|
||||
track: true,
|
||||
track_online: true,
|
||||
track_location: true,
|
||||
track_ship: true
|
||||
})
|
||||
end
|
||||
defp track_character(character_id, map_id),
|
||||
do:
|
||||
WandererApp.Character.TrackerManager.update_track_settings(character_id, %{
|
||||
map_id: map_id,
|
||||
track: true,
|
||||
track_online: true,
|
||||
track_location: true,
|
||||
track_ship: true
|
||||
})
|
||||
|
||||
defp _update_character(map_id, character_id) do
|
||||
{:ok, character} = WandererApp.Character.get_character(character_id)
|
||||
|
||||
@@ -162,6 +162,16 @@ defmodule WandererAppWeb.MapConnectionsEventHandler do
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_ui_event(
|
||||
"get_connection_info",
|
||||
%{"from" => from, "to" => to} = _event,
|
||||
%{assigns: %{map_id: map_id}} = socket
|
||||
) do
|
||||
{:ok, info} = map_id |> get_connection_info(from, to)
|
||||
|
||||
{:reply, info, socket}
|
||||
end
|
||||
|
||||
def handle_ui_event(
|
||||
"get_passages",
|
||||
%{"from" => from, "to" => to} = _event,
|
||||
@@ -194,4 +204,19 @@ defmodule WandererAppWeb.MapConnectionsEventHandler do
|
||||
|
||||
{:ok, %{passages: passages}}
|
||||
end
|
||||
|
||||
defp get_connection_info(map_id, from, to) do
|
||||
map_id
|
||||
|> WandererApp.Map.Server.get_connection_info(%{
|
||||
solar_system_source_id: "#{from}" |> String.to_integer(),
|
||||
solar_system_target_id: "#{to}" |> String.to_integer()
|
||||
})
|
||||
|> case do
|
||||
{:ok, info} ->
|
||||
{:ok, info}
|
||||
|
||||
_ ->
|
||||
{:ok, %{}}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -61,6 +61,7 @@ defmodule WandererAppWeb.MapEventHandler do
|
||||
@map_connection_ui_events [
|
||||
"manual_add_connection",
|
||||
"manual_delete_connection",
|
||||
"get_connection_info",
|
||||
"get_passages",
|
||||
"update_connection_time_status",
|
||||
"update_connection_mass_status",
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
defmodule WandererApp.Repo.Migrations.InstallAshFunctionsExtension420240922090427 do
|
||||
@moduledoc """
|
||||
Installs any extensions that are mentioned in the repo's `installed_extensions/0` callback
|
||||
|
||||
This file was autogenerated with `mix ash_postgres.generate_migrations`
|
||||
"""
|
||||
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
execute("""
|
||||
CREATE OR REPLACE FUNCTION uuid_generate_v7()
|
||||
RETURNS UUID
|
||||
AS $$
|
||||
DECLARE
|
||||
timestamp TIMESTAMPTZ;
|
||||
microseconds INT;
|
||||
BEGIN
|
||||
timestamp = clock_timestamp();
|
||||
microseconds = (cast(extract(microseconds FROM timestamp)::INT - (floor(extract(milliseconds FROM timestamp))::INT * 1000) AS DOUBLE PRECISION) * 4.096)::INT;
|
||||
|
||||
RETURN encode(
|
||||
set_byte(
|
||||
set_byte(
|
||||
overlay(uuid_send(gen_random_uuid()) placing substring(int8send(floor(extract(epoch FROM timestamp) * 1000)::BIGINT) FROM 3) FROM 1 FOR 6
|
||||
),
|
||||
6, (b'0111' || (microseconds >> 8)::bit(4))::bit(8)::int
|
||||
),
|
||||
7, microseconds::bit(8)::int
|
||||
),
|
||||
'hex')::UUID;
|
||||
END
|
||||
$$
|
||||
LANGUAGE PLPGSQL
|
||||
VOLATILE;
|
||||
""")
|
||||
|
||||
execute("""
|
||||
CREATE OR REPLACE FUNCTION timestamp_from_uuid_v7(_uuid uuid)
|
||||
RETURNS TIMESTAMP WITHOUT TIME ZONE
|
||||
AS $$
|
||||
SELECT to_timestamp(('x0000' || substr(_uuid::TEXT, 1, 8) || substr(_uuid::TEXT, 10, 4))::BIT(64)::BIGINT::NUMERIC / 1000);
|
||||
$$
|
||||
LANGUAGE SQL
|
||||
IMMUTABLE PARALLEL SAFE STRICT;
|
||||
""")
|
||||
end
|
||||
|
||||
def down do
|
||||
# Uncomment this if you actually want to uninstall the extensions
|
||||
# when this migration is rolled back:
|
||||
execute("DROP FUNCTION IF EXISTS uuid_generate_v7(), timestamp_from_uuid_v7(uuid)")
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user