mirror of
				https://github.com/wanderer-industries/wanderer
				synced 2025-11-04 00:14:52 +00:00 
			
		
		
		
	Compare commits
	
		
			22 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					a89c117612 | ||
| 
						 | 
					501dbcd76b | ||
| 
						 | 
					6039ac5d4f | ||
| 
						 | 
					48e87f3c47 | ||
| 
						 | 
					4fadcd5964 | ||
| 
						 | 
					6480154d1b | ||
| 
						 | 
					9c064531b8 | ||
| 
						 | 
					bee64c2570 | ||
| 
						 | 
					5393321953 | ||
| 
						 | 
					b44669da87 | ||
| 
						 | 
					9d8bf1529a | ||
| 
						 | 
					a514825eaf | ||
| 
						 | 
					8abcacb517 | ||
| 
						 | 
					a3fc55e63d | ||
| 
						 | 
					a4c1d5bf98 | ||
| 
						 | 
					b16bc615fa | ||
| 
						 | 
					10ec8d6b97 | ||
| 
						 | 
					b04f0c9183 | ||
| 
						 | 
					45e9ebb0d4 | ||
| 
						 | 
					ac3e68a49f | ||
| 
						 | 
					b35ef1151a | ||
| 
						 | 
					ebd01bebd4 | 
							
								
								
									
										15
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
# These are supported funding model platforms
 | 
			
		||||
 | 
			
		||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
 | 
			
		||||
patreon: WandererLtd
 | 
			
		||||
open_collective: # Replace with a single Open Collective username
 | 
			
		||||
ko_fi: # Replace with a single Ko-fi username
 | 
			
		||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
 | 
			
		||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
 | 
			
		||||
liberapay: # Replace with a single Liberapay username
 | 
			
		||||
issuehunt: # Replace with a single IssueHunt username
 | 
			
		||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
 | 
			
		||||
polar: # Replace with a single Polar username
 | 
			
		||||
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
 | 
			
		||||
thanks_dev: # Replace with a single thanks.dev username
 | 
			
		||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
 | 
			
		||||
							
								
								
									
										64
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										64
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -2,6 +2,70 @@
 | 
			
		||||
 | 
			
		||||
<!-- changelog -->
 | 
			
		||||
 | 
			
		||||
## [v1.0.15](https://github.com/wanderer-industries/wanderer/compare/v1.0.14...v1.0.15) (2024-09-21)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Bug Fixes:
 | 
			
		||||
 | 
			
		||||
* map: Show a proper user notification if map was deleted/archived
 | 
			
		||||
 | 
			
		||||
## [v1.0.14](https://github.com/wanderer-industries/wanderer/compare/v1.0.13...v1.0.14) (2024-09-21)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [v1.0.13](https://github.com/wanderer-industries/wanderer/compare/v1.0.12...v1.0.13) (2024-09-21)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Bug Fixes:
 | 
			
		||||
 | 
			
		||||
* tracking: Ensure user has at least one character tracked to work with map
 | 
			
		||||
 | 
			
		||||
## [v1.0.12](https://github.com/wanderer-industries/wanderer/compare/v1.0.11...v1.0.12) (2024-09-20)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Bug Fixes:
 | 
			
		||||
 | 
			
		||||
* audit: Hide character for non-character map activities
 | 
			
		||||
 | 
			
		||||
## [v1.0.11](https://github.com/wanderer-industries/wanderer/compare/v1.0.10...v1.0.11) (2024-09-20)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [v1.0.10](https://github.com/wanderer-industries/wanderer/compare/v1.0.9...v1.0.10) (2024-09-19)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Bug Fixes:
 | 
			
		||||
 | 
			
		||||
* signatures: Fix update signatures error if no character tracked on map
 | 
			
		||||
 | 
			
		||||
## [v1.0.9](https://github.com/wanderer-industries/wanderer/compare/v1.0.8...v1.0.9) (2024-09-19)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Bug Fixes:
 | 
			
		||||
 | 
			
		||||
* core: Fix system add error if it's already added on map
 | 
			
		||||
 | 
			
		||||
## [v1.0.8](https://github.com/wanderer-industries/wanderer/compare/v1.0.7...v1.0.8) (2024-09-19)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Bug Fixes:
 | 
			
		||||
 | 
			
		||||
* docker: Fix DB connection in docker-compose internal network
 | 
			
		||||
 | 
			
		||||
## [v1.0.7](https://github.com/wanderer-industries/wanderer/compare/v1.0.6...v1.0.7) (2024-09-19)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,22 +1,6 @@
 | 
			
		||||
import Config
 | 
			
		||||
import WandererApp.ConfigHelpers
 | 
			
		||||
 | 
			
		||||
# config/runtime.exs is executed for all environments, including
 | 
			
		||||
# during releases. It is executed after compilation and before the
 | 
			
		||||
# system starts, so it is typically used to load production configuration
 | 
			
		||||
# and secrets from environment variables or elsewhere. Do not define
 | 
			
		||||
# any compile-time configuration in here, as it won't be applied.
 | 
			
		||||
# The block below contains prod specific runtime configuration.
 | 
			
		||||
 | 
			
		||||
# ## Using releases
 | 
			
		||||
#
 | 
			
		||||
# If you use `mix release`, you need to explicitly enable the server
 | 
			
		||||
# by passing the PHX_SERVER=true when you start it:
 | 
			
		||||
#
 | 
			
		||||
#     PHX_SERVER=true bin/wanderer_app start
 | 
			
		||||
#
 | 
			
		||||
# Alternatively, you can use `mix phx.gen.release` to generate a `bin/server`
 | 
			
		||||
# script that automatically sets the env var above.
 | 
			
		||||
if System.get_env("PHX_SERVER") do
 | 
			
		||||
  config :wanderer_app, WandererAppWeb.Endpoint, server: true
 | 
			
		||||
end
 | 
			
		||||
@@ -69,6 +53,15 @@ map_subscriptions_enabled =
 | 
			
		||||
  |> get_var_from_path_or_env("WANDERER_MAP_SUBSCRIPTIONS_ENABLED", "false")
 | 
			
		||||
  |> String.to_existing_atom()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
map_subscription_characters_limit =
 | 
			
		||||
  config_dir
 | 
			
		||||
  |> get_int_from_path_or_env("WANDERER_MAP_SUBSCRIPTION_CHARACTERS_LIMIT", 100)
 | 
			
		||||
 | 
			
		||||
map_subscription_hubs_limit =
 | 
			
		||||
  config_dir
 | 
			
		||||
  |> get_int_from_path_or_env("WANDERER_MAP_SUBSCRIPTION_HUBS_LIMIT", 10)
 | 
			
		||||
 | 
			
		||||
wallet_tracking_enabled =
 | 
			
		||||
  config_dir
 | 
			
		||||
  |> get_var_from_path_or_env("WANDERER_WALLET_TRACKING_ENABLED", "false")
 | 
			
		||||
@@ -93,7 +86,7 @@ config :wanderer_app,
 | 
			
		||||
  wallet_tracking_enabled: wallet_tracking_enabled,
 | 
			
		||||
  subscription_settings: %{
 | 
			
		||||
    plans: [
 | 
			
		||||
      %{id: "alpha", characters_limit: 100, hubs_limit: 10, base_price: 0, monthly_discount: 0},
 | 
			
		||||
      %{id: "alpha", characters_limit: map_subscription_characters_limit, hubs_limit: map_subscription_hubs_limit, base_price: 0, monthly_discount: 0},
 | 
			
		||||
      %{
 | 
			
		||||
        id: "omega",
 | 
			
		||||
        characters_limit: 300,
 | 
			
		||||
@@ -178,10 +171,23 @@ if config_env() == :prod do
 | 
			
		||||
      For example: ecto://USER:PASS@HOST/DATABASE
 | 
			
		||||
      """
 | 
			
		||||
 | 
			
		||||
  maybe_ipv6 = if System.get_env("ECTO_IPV6") in ~w(true 1), do: [:inet6], else: []
 | 
			
		||||
  maybe_ipv6 =
 | 
			
		||||
    config_dir
 | 
			
		||||
    |> get_var_from_path_or_env("ECTO_IPV6", "false")
 | 
			
		||||
    |> String.to_existing_atom()
 | 
			
		||||
    |> case do
 | 
			
		||||
      true -> [:inet6]
 | 
			
		||||
      _ -> []
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
  db_ssl_enabled =
 | 
			
		||||
    config_dir
 | 
			
		||||
    |> get_var_from_path_or_env("DATABASE_SSL_ENABLED", "false")
 | 
			
		||||
    |> String.to_existing_atom()
 | 
			
		||||
 | 
			
		||||
  config :wanderer_app, WandererApp.Repo,
 | 
			
		||||
    url: database_url,
 | 
			
		||||
    ssl: db_ssl_enabled,
 | 
			
		||||
    pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
 | 
			
		||||
    socket_options: maybe_ipv6
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1657,32 +1657,35 @@ defmodule WandererApp.Map.Server.Impl do
 | 
			
		||||
            {:ok, solar_system_info} =
 | 
			
		||||
              WandererApp.Api.MapSolarSystem.by_solar_system_id(location.solar_system_id)
 | 
			
		||||
 | 
			
		||||
            {:ok, new_system} =
 | 
			
		||||
              WandererApp.MapSystemRepo.create(%{
 | 
			
		||||
                map_id: map_id,
 | 
			
		||||
                solar_system_id: location.solar_system_id,
 | 
			
		||||
                name: solar_system_info.solar_system_name,
 | 
			
		||||
                position_x: position.x,
 | 
			
		||||
                position_y: position.y
 | 
			
		||||
              })
 | 
			
		||||
                  map_id: map_id,
 | 
			
		||||
                  solar_system_id: location.solar_system_id,
 | 
			
		||||
                  name: solar_system_info.solar_system_name,
 | 
			
		||||
                  position_x: position.x,
 | 
			
		||||
                  position_y: position.y
 | 
			
		||||
                })
 | 
			
		||||
                |> case do
 | 
			
		||||
                  {:ok, new_system} ->
 | 
			
		||||
                    @ddrt.insert(
 | 
			
		||||
                      {new_system.solar_system_id,
 | 
			
		||||
                      WandererApp.Map.PositionCalculator.get_system_bounding_rect(new_system)},
 | 
			
		||||
                      rtree_name
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
            @ddrt.insert(
 | 
			
		||||
              {new_system.solar_system_id,
 | 
			
		||||
               WandererApp.Map.PositionCalculator.get_system_bounding_rect(new_system)},
 | 
			
		||||
              rtree_name
 | 
			
		||||
            )
 | 
			
		||||
                    WandererApp.Cache.put(
 | 
			
		||||
                      "map_#{map_id}:system_#{new_system.id}:last_activity",
 | 
			
		||||
                      DateTime.utc_now(),
 | 
			
		||||
                      ttl: @system_inactive_timeout
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
            WandererApp.Cache.put(
 | 
			
		||||
              "map_#{map_id}:system_#{new_system.id}:last_activity",
 | 
			
		||||
              DateTime.utc_now(),
 | 
			
		||||
              ttl: @system_inactive_timeout
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            broadcast!(map_id, :add_system, new_system)
 | 
			
		||||
            WandererApp.Map.add_system(map_id, new_system)
 | 
			
		||||
                    broadcast!(map_id, :add_system, new_system)
 | 
			
		||||
                    WandererApp.Map.add_system(map_id, new_system)
 | 
			
		||||
                  _ ->
 | 
			
		||||
                    :ok
 | 
			
		||||
                end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
      {:error, :already_exists} ->
 | 
			
		||||
      {:error, _} ->
 | 
			
		||||
        :ok
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 
 | 
			
		||||
@@ -51,7 +51,7 @@ defmodule WandererAppWeb.Alerts do
 | 
			
		||||
  def delayed_fade_out_flash() do
 | 
			
		||||
    JS.hide(
 | 
			
		||||
      transition:
 | 
			
		||||
        {"transition-opacity ease-out delay-2000 duration-1000", "opacity-100", "opacity-0"},
 | 
			
		||||
        {"transition-opacity ease-out delay-5000 duration-6000", "opacity-100", "opacity-0"},
 | 
			
		||||
      time: 6000
 | 
			
		||||
    )
 | 
			
		||||
    |> JS.push("lv:clear-flash")
 | 
			
		||||
 
 | 
			
		||||
@@ -42,27 +42,30 @@
 | 
			
		||||
      integrity={integrity_hash("https://unpkg.com/react-dom@18/umd/react-dom.production.min.js")}
 | 
			
		||||
    >
 | 
			
		||||
    </script>
 | 
			
		||||
 | 
			
		||||
    <script defer phx-track-static type="module" src={~p"/assets/app.js"} crossorigin="anonymous">
 | 
			
		||||
    </script>
 | 
			
		||||
 | 
			
		||||
    <!-- Appzi: Capture Insightful Feedback -->
 | 
			
		||||
    <script async src="https://w.appzi.io/w.js?token=yddv0">
 | 
			
		||||
    <script defer src="https://w.appzi.io/w.js?token=yddv0">
 | 
			
		||||
    </script>
 | 
			
		||||
    <!-- End Appzi -->
 | 
			
		||||
 | 
			
		||||
    <!-- Google tag (gtag.js) -->
 | 
			
		||||
    <script
 | 
			
		||||
      async
 | 
			
		||||
      defer
 | 
			
		||||
      src="https://www.googletagmanager.com/gtag/js?id=G-61PHLLS0LD"
 | 
			
		||||
      crossorigin="anonymous"
 | 
			
		||||
    >
 | 
			
		||||
    </script>
 | 
			
		||||
    <script>
 | 
			
		||||
    <script defer>
 | 
			
		||||
      window.dataLayer = window.dataLayer || [];
 | 
			
		||||
      function gtag(){dataLayer.push(arguments);}
 | 
			
		||||
      gtag('js', new Date());
 | 
			
		||||
 | 
			
		||||
      gtag('config', 'G-61PHLLS0LD');
 | 
			
		||||
    </script>
 | 
			
		||||
    <script defer phx-track-static type="module" src={~p"/assets/app.js"} crossorigin="anonymous">
 | 
			
		||||
    </script>
 | 
			
		||||
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
    <%= @inner_content %>
 | 
			
		||||
 
 | 
			
		||||
@@ -46,7 +46,7 @@ defmodule WandererAppWeb.UserActivity do
 | 
			
		||||
            <.local_time id={@activity.id} at={@activity.inserted_at} />
 | 
			
		||||
          </span>
 | 
			
		||||
        </p>
 | 
			
		||||
        <p class="flex shrink-0 items-center space-x-1 min-w-[200px]">
 | 
			
		||||
        <p :if={not is_nil(@activity.character)} class="flex shrink-0 items-center space-x-1 min-w-[200px]">
 | 
			
		||||
          <.character_item character={@activity.character} />
 | 
			
		||||
        </p>
 | 
			
		||||
      </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -64,6 +64,18 @@ defmodule WandererAppWeb.MapLive do
 | 
			
		||||
          timeout: 2000
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
      {:ok,
 | 
			
		||||
        %{
 | 
			
		||||
          deleted: true
 | 
			
		||||
        } = map} ->
 | 
			
		||||
 | 
			
		||||
        socket
 | 
			
		||||
        |> put_flash(
 | 
			
		||||
          :error,
 | 
			
		||||
          "Map was deleted by owner or administrator."
 | 
			
		||||
        )
 | 
			
		||||
        |> push_navigate(to: ~p"/maps")
 | 
			
		||||
 | 
			
		||||
      {:error, _} ->
 | 
			
		||||
        socket
 | 
			
		||||
        |> put_flash(
 | 
			
		||||
@@ -386,6 +398,13 @@ defmodule WandererAppWeb.MapLive do
 | 
			
		||||
                  "One of your characters has expired token. Please refresh it on characters page."
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
              :empty_tracked_characters ->
 | 
			
		||||
                socket
 | 
			
		||||
                |> put_flash(
 | 
			
		||||
                  :info,
 | 
			
		||||
                  "You should enable tracking for at least one character to work with map."
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
              :map_character_limit ->
 | 
			
		||||
                socket
 | 
			
		||||
                |> put_flash(
 | 
			
		||||
@@ -400,7 +419,7 @@ defmodule WandererAppWeb.MapLive do
 | 
			
		||||
 | 
			
		||||
        {:noreply,
 | 
			
		||||
         socket
 | 
			
		||||
         |> assign(map_loaded?: true, user_characters: user_character_eve_ids)
 | 
			
		||||
         |> assign(map_loaded?: true, user_characters: user_character_eve_ids, has_tracked_characters?: _has_tracked_characters?(user_character_eve_ids))
 | 
			
		||||
         |> _push_map_event("init", initial_data)
 | 
			
		||||
         |> push_event("js-exec", %{
 | 
			
		||||
           to: "#map-loader",
 | 
			
		||||
@@ -470,16 +489,24 @@ defmodule WandererAppWeb.MapLive do
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @impl true
 | 
			
		||||
  def handle_event("manual_add_system", %{"coordinates" => coordinates} = _event, socket) do
 | 
			
		||||
    case _check_user_permissions(socket, :add_system) do
 | 
			
		||||
  def handle_event("manual_add_system", %{"coordinates" => coordinates} = _event, %{assigns: %{has_tracked_characters?: has_tracked_characters?}} = socket) do
 | 
			
		||||
    case has_tracked_characters? do
 | 
			
		||||
      true ->
 | 
			
		||||
        {:noreply,
 | 
			
		||||
         socket
 | 
			
		||||
         |> assign(coordinates: coordinates)
 | 
			
		||||
         |> push_patch(to: ~p"/#{socket.assigns.map_slug}/add-system")}
 | 
			
		||||
        case _check_user_permissions(socket, :add_system) do
 | 
			
		||||
          true ->
 | 
			
		||||
            {:noreply,
 | 
			
		||||
            socket
 | 
			
		||||
            |> assign(coordinates: coordinates)
 | 
			
		||||
            |> push_patch(to: ~p"/#{socket.assigns.map_slug}/add-system")}
 | 
			
		||||
 | 
			
		||||
          _ ->
 | 
			
		||||
            {:noreply, socket}
 | 
			
		||||
        end
 | 
			
		||||
      _ ->
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
        {:noreply, socket |> put_flash(
 | 
			
		||||
          :error,
 | 
			
		||||
          "You should enable tracking for at least one character to add system."
 | 
			
		||||
        )}
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
@@ -487,157 +514,189 @@ defmodule WandererAppWeb.MapLive do
 | 
			
		||||
  def handle_event(
 | 
			
		||||
        "manual_add_connection",
 | 
			
		||||
        %{"source" => solar_system_source_id, "target" => solar_system_target_id} = _event,
 | 
			
		||||
        %{assigns: %{current_user: current_user, tracked_character_ids: tracked_character_ids}} =
 | 
			
		||||
        %{assigns: %{current_user: current_user, tracked_character_ids: tracked_character_ids, has_tracked_characters?: has_tracked_characters?}} =
 | 
			
		||||
          socket
 | 
			
		||||
      ) do
 | 
			
		||||
    case _check_user_permissions(socket, :add_connection) do
 | 
			
		||||
      true ->
 | 
			
		||||
        map_id =
 | 
			
		||||
          socket
 | 
			
		||||
          |> map_id()
 | 
			
		||||
          case has_tracked_characters? do
 | 
			
		||||
            true ->
 | 
			
		||||
              case _check_user_permissions(socket, :add_connection) do
 | 
			
		||||
                true ->
 | 
			
		||||
                  map_id =
 | 
			
		||||
                    socket
 | 
			
		||||
                    |> map_id()
 | 
			
		||||
 | 
			
		||||
        map_id
 | 
			
		||||
        |> WandererApp.Map.Server.add_connection(%{
 | 
			
		||||
          solar_system_source_id: solar_system_source_id |> String.to_integer(),
 | 
			
		||||
          solar_system_target_id: solar_system_target_id |> String.to_integer()
 | 
			
		||||
        })
 | 
			
		||||
                  map_id
 | 
			
		||||
                  |> WandererApp.Map.Server.add_connection(%{
 | 
			
		||||
                    solar_system_source_id: solar_system_source_id |> String.to_integer(),
 | 
			
		||||
                    solar_system_target_id: solar_system_target_id |> String.to_integer()
 | 
			
		||||
                  })
 | 
			
		||||
 | 
			
		||||
        :telemetry.execute([:wanderer_app, :map, :connection, :add], %{count: 1}, %{
 | 
			
		||||
          character_id: tracked_character_ids |> List.first(),
 | 
			
		||||
          user_id: current_user.id,
 | 
			
		||||
          map_id: map_id,
 | 
			
		||||
          solar_system_source_id: "#{solar_system_source_id}" |> String.to_integer(),
 | 
			
		||||
          solar_system_target_id: "#{solar_system_target_id}" |> String.to_integer()
 | 
			
		||||
        })
 | 
			
		||||
                  :telemetry.execute([:wanderer_app, :map, :connection, :add], %{count: 1}, %{
 | 
			
		||||
                    character_id: tracked_character_ids |> List.first(),
 | 
			
		||||
                    user_id: current_user.id,
 | 
			
		||||
                    map_id: map_id,
 | 
			
		||||
                    solar_system_source_id: "#{solar_system_source_id}" |> String.to_integer(),
 | 
			
		||||
                    solar_system_target_id: "#{solar_system_target_id}" |> String.to_integer()
 | 
			
		||||
                  })
 | 
			
		||||
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
                  {:noreply, socket}
 | 
			
		||||
 | 
			
		||||
      _ ->
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
    end
 | 
			
		||||
                _ ->
 | 
			
		||||
                  {:noreply, socket}
 | 
			
		||||
              end
 | 
			
		||||
            _ ->
 | 
			
		||||
              {:noreply, socket |> put_flash(
 | 
			
		||||
                :error,
 | 
			
		||||
                "You should enable tracking for at least one character to add connection."
 | 
			
		||||
              )}
 | 
			
		||||
          end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @impl true
 | 
			
		||||
  def handle_event(
 | 
			
		||||
        "add_hub",
 | 
			
		||||
        %{"system_id" => solar_system_id} = _event,
 | 
			
		||||
        %{assigns: %{current_user: current_user, tracked_character_ids: tracked_character_ids}} =
 | 
			
		||||
        %{assigns: %{current_user: current_user, tracked_character_ids: tracked_character_ids, has_tracked_characters?: has_tracked_characters?}} =
 | 
			
		||||
          socket
 | 
			
		||||
      ) do
 | 
			
		||||
    case _check_user_permissions(socket, :update_system) do
 | 
			
		||||
      true ->
 | 
			
		||||
        map_id =
 | 
			
		||||
          socket
 | 
			
		||||
          |> map_id()
 | 
			
		||||
        case has_tracked_characters? do
 | 
			
		||||
          true ->
 | 
			
		||||
            case _check_user_permissions(socket, :update_system) do
 | 
			
		||||
              true ->
 | 
			
		||||
                map_id =
 | 
			
		||||
                  socket
 | 
			
		||||
                  |> map_id()
 | 
			
		||||
 | 
			
		||||
        :telemetry.execute([:wanderer_app, :map, :hub, :add], %{count: 1}, %{
 | 
			
		||||
          character_id: tracked_character_ids |> List.first(),
 | 
			
		||||
          user_id: current_user.id,
 | 
			
		||||
          map_id: map_id,
 | 
			
		||||
          solar_system_id: solar_system_id
 | 
			
		||||
        })
 | 
			
		||||
                :telemetry.execute([:wanderer_app, :map, :hub, :add], %{count: 1}, %{
 | 
			
		||||
                  character_id: tracked_character_ids |> List.first(),
 | 
			
		||||
                  user_id: current_user.id,
 | 
			
		||||
                  map_id: map_id,
 | 
			
		||||
                  solar_system_id: solar_system_id
 | 
			
		||||
                })
 | 
			
		||||
 | 
			
		||||
        map_id
 | 
			
		||||
        |> WandererApp.Map.Server.add_hub(%{
 | 
			
		||||
          solar_system_id: solar_system_id
 | 
			
		||||
        })
 | 
			
		||||
                map_id
 | 
			
		||||
                |> WandererApp.Map.Server.add_hub(%{
 | 
			
		||||
                  solar_system_id: solar_system_id
 | 
			
		||||
                })
 | 
			
		||||
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
                {:noreply, socket}
 | 
			
		||||
 | 
			
		||||
      _ ->
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
    end
 | 
			
		||||
              _ ->
 | 
			
		||||
                {:noreply, socket}
 | 
			
		||||
            end
 | 
			
		||||
          _ ->
 | 
			
		||||
            {:noreply, socket |> put_flash(
 | 
			
		||||
              :error,
 | 
			
		||||
              "You should enable tracking for at least one character to add hub."
 | 
			
		||||
            )}
 | 
			
		||||
        end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @impl true
 | 
			
		||||
  def handle_event(
 | 
			
		||||
        "delete_hub",
 | 
			
		||||
        %{"system_id" => solar_system_id} = _event,
 | 
			
		||||
        %{assigns: %{current_user: current_user, tracked_character_ids: tracked_character_ids}} =
 | 
			
		||||
        %{assigns: %{current_user: current_user, tracked_character_ids: tracked_character_ids, has_tracked_characters?: has_tracked_characters?}} =
 | 
			
		||||
          socket
 | 
			
		||||
      ) do
 | 
			
		||||
    case _check_user_permissions(socket, :update_system) do
 | 
			
		||||
      true ->
 | 
			
		||||
        map_id =
 | 
			
		||||
          socket
 | 
			
		||||
          |> map_id()
 | 
			
		||||
        case has_tracked_characters? do
 | 
			
		||||
          true ->
 | 
			
		||||
            case _check_user_permissions(socket, :update_system) do
 | 
			
		||||
              true ->
 | 
			
		||||
                map_id =
 | 
			
		||||
                  socket
 | 
			
		||||
                  |> map_id()
 | 
			
		||||
 | 
			
		||||
        :telemetry.execute([:wanderer_app, :map, :hub, :remove], %{count: 1}, %{
 | 
			
		||||
          character_id: tracked_character_ids |> List.first(),
 | 
			
		||||
          user_id: current_user.id,
 | 
			
		||||
          map_id: map_id,
 | 
			
		||||
          solar_system_id: solar_system_id
 | 
			
		||||
        })
 | 
			
		||||
                :telemetry.execute([:wanderer_app, :map, :hub, :remove], %{count: 1}, %{
 | 
			
		||||
                  character_id: tracked_character_ids |> List.first(),
 | 
			
		||||
                  user_id: current_user.id,
 | 
			
		||||
                  map_id: map_id,
 | 
			
		||||
                  solar_system_id: solar_system_id
 | 
			
		||||
                })
 | 
			
		||||
 | 
			
		||||
        map_id
 | 
			
		||||
        |> WandererApp.Map.Server.remove_hub(%{
 | 
			
		||||
          solar_system_id: solar_system_id
 | 
			
		||||
        })
 | 
			
		||||
                map_id
 | 
			
		||||
                |> WandererApp.Map.Server.remove_hub(%{
 | 
			
		||||
                  solar_system_id: solar_system_id
 | 
			
		||||
                })
 | 
			
		||||
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
                {:noreply, socket}
 | 
			
		||||
 | 
			
		||||
      _ ->
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
    end
 | 
			
		||||
              _ ->
 | 
			
		||||
                {:noreply, socket}
 | 
			
		||||
            end
 | 
			
		||||
          _ ->
 | 
			
		||||
            {:noreply, socket |> put_flash(
 | 
			
		||||
              :error,
 | 
			
		||||
              "You should enable tracking for at least one character to remove hub."
 | 
			
		||||
            )}
 | 
			
		||||
        end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @impl true
 | 
			
		||||
  def handle_event(
 | 
			
		||||
        "update_system_" <> param,
 | 
			
		||||
        %{"system_id" => solar_system_id, "value" => value} = _event,
 | 
			
		||||
        %{assigns: %{current_user: current_user, tracked_character_ids: tracked_character_ids}} =
 | 
			
		||||
        %{assigns: %{current_user: current_user, tracked_character_ids: tracked_character_ids, has_tracked_characters?: has_tracked_characters?}} =
 | 
			
		||||
          socket
 | 
			
		||||
      ) do
 | 
			
		||||
    case _check_user_permissions(socket, :update_system) do
 | 
			
		||||
      true ->
 | 
			
		||||
        method_atom =
 | 
			
		||||
          case param do
 | 
			
		||||
            "name" -> :update_system_name
 | 
			
		||||
            "description" -> :update_system_description
 | 
			
		||||
            "labels" -> :update_system_labels
 | 
			
		||||
            "locked" -> :update_system_locked
 | 
			
		||||
            "tag" -> :update_system_tag
 | 
			
		||||
            "status" -> :update_system_status
 | 
			
		||||
            _ -> nil
 | 
			
		||||
          end
 | 
			
		||||
        case has_tracked_characters? do
 | 
			
		||||
          true ->
 | 
			
		||||
            case _check_user_permissions(socket, :update_system) do
 | 
			
		||||
              true ->
 | 
			
		||||
                method_atom =
 | 
			
		||||
                  case param do
 | 
			
		||||
                    "name" -> :update_system_name
 | 
			
		||||
                    "description" -> :update_system_description
 | 
			
		||||
                    "labels" -> :update_system_labels
 | 
			
		||||
                    "locked" -> :update_system_locked
 | 
			
		||||
                    "tag" -> :update_system_tag
 | 
			
		||||
                    "status" -> :update_system_status
 | 
			
		||||
                    _ -> nil
 | 
			
		||||
                  end
 | 
			
		||||
 | 
			
		||||
        key_atom =
 | 
			
		||||
          case param do
 | 
			
		||||
            "name" -> :name
 | 
			
		||||
            "description" -> :description
 | 
			
		||||
            "labels" -> :labels
 | 
			
		||||
            "locked" -> :locked
 | 
			
		||||
            "tag" -> :tag
 | 
			
		||||
            "status" -> :status
 | 
			
		||||
            _ -> :none
 | 
			
		||||
          end
 | 
			
		||||
                key_atom =
 | 
			
		||||
                  case param do
 | 
			
		||||
                    "name" -> :name
 | 
			
		||||
                    "description" -> :description
 | 
			
		||||
                    "labels" -> :labels
 | 
			
		||||
                    "locked" -> :locked
 | 
			
		||||
                    "tag" -> :tag
 | 
			
		||||
                    "status" -> :status
 | 
			
		||||
                    _ -> :none
 | 
			
		||||
                  end
 | 
			
		||||
 | 
			
		||||
        map_id =
 | 
			
		||||
          socket
 | 
			
		||||
          |> map_id()
 | 
			
		||||
                map_id =
 | 
			
		||||
                  socket
 | 
			
		||||
                  |> map_id()
 | 
			
		||||
 | 
			
		||||
        :telemetry.execute([:wanderer_app, :map, :system, :update], %{count: 1}, %{
 | 
			
		||||
          character_id: tracked_character_ids |> List.first(),
 | 
			
		||||
          user_id: current_user.id,
 | 
			
		||||
          map_id: map_id,
 | 
			
		||||
          solar_system_id: "#{solar_system_id}" |> String.to_integer(),
 | 
			
		||||
          key: key_atom,
 | 
			
		||||
          value: value
 | 
			
		||||
        })
 | 
			
		||||
                :telemetry.execute([:wanderer_app, :map, :system, :update], %{count: 1}, %{
 | 
			
		||||
                  character_id: tracked_character_ids |> List.first(),
 | 
			
		||||
                  user_id: current_user.id,
 | 
			
		||||
                  map_id: map_id,
 | 
			
		||||
                  solar_system_id: "#{solar_system_id}" |> String.to_integer(),
 | 
			
		||||
                  key: key_atom,
 | 
			
		||||
                  value: value
 | 
			
		||||
                })
 | 
			
		||||
 | 
			
		||||
        apply(WandererApp.Map.Server, method_atom, [
 | 
			
		||||
          map_id,
 | 
			
		||||
          %{
 | 
			
		||||
            solar_system_id: "#{solar_system_id}" |> String.to_integer()
 | 
			
		||||
          }
 | 
			
		||||
          |> Map.put_new(key_atom, value)
 | 
			
		||||
        ])
 | 
			
		||||
                apply(WandererApp.Map.Server, method_atom, [
 | 
			
		||||
                  map_id,
 | 
			
		||||
                  %{
 | 
			
		||||
                    solar_system_id: "#{solar_system_id}" |> String.to_integer()
 | 
			
		||||
                  }
 | 
			
		||||
                  |> Map.put_new(key_atom, value)
 | 
			
		||||
                ])
 | 
			
		||||
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
                {:noreply, socket}
 | 
			
		||||
 | 
			
		||||
      _ ->
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
    end
 | 
			
		||||
              _ ->
 | 
			
		||||
                {:noreply, socket}
 | 
			
		||||
            end
 | 
			
		||||
          _ ->
 | 
			
		||||
            {:noreply, socket |> put_flash(
 | 
			
		||||
              :error,
 | 
			
		||||
              "You should enable tracking for at least one character to update system."
 | 
			
		||||
            )}
 | 
			
		||||
        end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @impl true
 | 
			
		||||
@@ -648,57 +707,65 @@ defmodule WandererAppWeb.MapLive do
 | 
			
		||||
          "target" => solar_system_target_id,
 | 
			
		||||
          "value" => value
 | 
			
		||||
        } = _event,
 | 
			
		||||
        %{assigns: %{current_user: current_user, tracked_character_ids: tracked_character_ids}} =
 | 
			
		||||
        %{assigns: %{current_user: current_user, tracked_character_ids: tracked_character_ids, has_tracked_characters?: has_tracked_characters?}} =
 | 
			
		||||
          socket
 | 
			
		||||
      ) do
 | 
			
		||||
    case _check_user_permissions(socket, :update_system) do
 | 
			
		||||
      true ->
 | 
			
		||||
        method_atom =
 | 
			
		||||
          case param do
 | 
			
		||||
            "time_status" -> :update_connection_time_status
 | 
			
		||||
            "mass_status" -> :update_connection_mass_status
 | 
			
		||||
            "ship_size_type" -> :update_connection_ship_size_type
 | 
			
		||||
            "locked" -> :update_connection_locked
 | 
			
		||||
            _ -> nil
 | 
			
		||||
          end
 | 
			
		||||
        case has_tracked_characters? do
 | 
			
		||||
          true ->
 | 
			
		||||
            case _check_user_permissions(socket, :update_system) do
 | 
			
		||||
              true ->
 | 
			
		||||
                method_atom =
 | 
			
		||||
                  case param do
 | 
			
		||||
                    "time_status" -> :update_connection_time_status
 | 
			
		||||
                    "mass_status" -> :update_connection_mass_status
 | 
			
		||||
                    "ship_size_type" -> :update_connection_ship_size_type
 | 
			
		||||
                    "locked" -> :update_connection_locked
 | 
			
		||||
                    _ -> nil
 | 
			
		||||
                  end
 | 
			
		||||
 | 
			
		||||
        key_atom =
 | 
			
		||||
          case param do
 | 
			
		||||
            "time_status" -> :time_status
 | 
			
		||||
            "mass_status" -> :mass_status
 | 
			
		||||
            "ship_size_type" -> :ship_size_type
 | 
			
		||||
            "locked" -> :locked
 | 
			
		||||
            _ -> nil
 | 
			
		||||
          end
 | 
			
		||||
                key_atom =
 | 
			
		||||
                  case param do
 | 
			
		||||
                    "time_status" -> :time_status
 | 
			
		||||
                    "mass_status" -> :mass_status
 | 
			
		||||
                    "ship_size_type" -> :ship_size_type
 | 
			
		||||
                    "locked" -> :locked
 | 
			
		||||
                    _ -> nil
 | 
			
		||||
                  end
 | 
			
		||||
 | 
			
		||||
        map_id =
 | 
			
		||||
          socket
 | 
			
		||||
          |> map_id()
 | 
			
		||||
                map_id =
 | 
			
		||||
                  socket
 | 
			
		||||
                  |> map_id()
 | 
			
		||||
 | 
			
		||||
        :telemetry.execute([:wanderer_app, :map, :connection, :update], %{count: 1}, %{
 | 
			
		||||
          character_id: tracked_character_ids |> List.first(),
 | 
			
		||||
          user_id: current_user.id,
 | 
			
		||||
          map_id: map_id,
 | 
			
		||||
          solar_system_source_id: "#{solar_system_source_id}" |> String.to_integer(),
 | 
			
		||||
          solar_system_target_id: "#{solar_system_target_id}" |> String.to_integer(),
 | 
			
		||||
          key: key_atom,
 | 
			
		||||
          value: value
 | 
			
		||||
        })
 | 
			
		||||
                :telemetry.execute([:wanderer_app, :map, :connection, :update], %{count: 1}, %{
 | 
			
		||||
                  character_id: tracked_character_ids |> List.first(),
 | 
			
		||||
                  user_id: current_user.id,
 | 
			
		||||
                  map_id: map_id,
 | 
			
		||||
                  solar_system_source_id: "#{solar_system_source_id}" |> String.to_integer(),
 | 
			
		||||
                  solar_system_target_id: "#{solar_system_target_id}" |> String.to_integer(),
 | 
			
		||||
                  key: key_atom,
 | 
			
		||||
                  value: value
 | 
			
		||||
                })
 | 
			
		||||
 | 
			
		||||
        apply(WandererApp.Map.Server, method_atom, [
 | 
			
		||||
          map_id,
 | 
			
		||||
          %{
 | 
			
		||||
            solar_system_source_id: "#{solar_system_source_id}" |> String.to_integer(),
 | 
			
		||||
            solar_system_target_id: "#{solar_system_target_id}" |> String.to_integer()
 | 
			
		||||
          }
 | 
			
		||||
          |> Map.put_new(key_atom, value)
 | 
			
		||||
        ])
 | 
			
		||||
                apply(WandererApp.Map.Server, method_atom, [
 | 
			
		||||
                  map_id,
 | 
			
		||||
                  %{
 | 
			
		||||
                    solar_system_source_id: "#{solar_system_source_id}" |> String.to_integer(),
 | 
			
		||||
                    solar_system_target_id: "#{solar_system_target_id}" |> String.to_integer()
 | 
			
		||||
                  }
 | 
			
		||||
                  |> Map.put_new(key_atom, value)
 | 
			
		||||
                ])
 | 
			
		||||
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
                {:noreply, socket}
 | 
			
		||||
 | 
			
		||||
      _ ->
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
    end
 | 
			
		||||
              _ ->
 | 
			
		||||
                {:noreply, socket}
 | 
			
		||||
            end
 | 
			
		||||
          _ ->
 | 
			
		||||
            {:noreply, socket |> put_flash(
 | 
			
		||||
              :error,
 | 
			
		||||
              "You should enable tracking for at least one character to update connection."
 | 
			
		||||
            )}
 | 
			
		||||
        end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @impl true
 | 
			
		||||
@@ -724,47 +791,55 @@ defmodule WandererAppWeb.MapLive do
 | 
			
		||||
            first_character_eve_id =
 | 
			
		||||
              Map.get(socket.assigns, :user_characters, []) |> List.first()
 | 
			
		||||
 | 
			
		||||
            added_signatures =
 | 
			
		||||
              added_signatures
 | 
			
		||||
              |> _parse_signatures(first_character_eve_id, system.id)
 | 
			
		||||
            case not is_nil(first_character_eve_id) do
 | 
			
		||||
              true ->
 | 
			
		||||
                added_signatures =
 | 
			
		||||
                  added_signatures
 | 
			
		||||
                  |> _parse_signatures(first_character_eve_id, system.id)
 | 
			
		||||
 | 
			
		||||
            updated_signatures =
 | 
			
		||||
              updated_signatures
 | 
			
		||||
              |> _parse_signatures(first_character_eve_id, system.id)
 | 
			
		||||
                updated_signatures =
 | 
			
		||||
                  updated_signatures
 | 
			
		||||
                  |> _parse_signatures(first_character_eve_id, system.id)
 | 
			
		||||
 | 
			
		||||
            updated_signatures_eve_ids =
 | 
			
		||||
              updated_signatures
 | 
			
		||||
              |> Enum.map(fn s -> s.eve_id end)
 | 
			
		||||
                updated_signatures_eve_ids =
 | 
			
		||||
                  updated_signatures
 | 
			
		||||
                  |> Enum.map(fn s -> s.eve_id end)
 | 
			
		||||
 | 
			
		||||
            removed_signatures_eve_ids =
 | 
			
		||||
              removed_signatures
 | 
			
		||||
              |> _parse_signatures(first_character_eve_id, system.id)
 | 
			
		||||
              |> Enum.map(fn s -> s.eve_id end)
 | 
			
		||||
                removed_signatures_eve_ids =
 | 
			
		||||
                  removed_signatures
 | 
			
		||||
                  |> _parse_signatures(first_character_eve_id, system.id)
 | 
			
		||||
                  |> Enum.map(fn s -> s.eve_id end)
 | 
			
		||||
 | 
			
		||||
            WandererApp.Api.MapSystemSignature.by_system_id!(system.id)
 | 
			
		||||
            |> Enum.filter(fn s -> s.eve_id in removed_signatures_eve_ids end)
 | 
			
		||||
            |> Enum.each(fn s ->
 | 
			
		||||
              s
 | 
			
		||||
              |> Ash.destroy!()
 | 
			
		||||
            end)
 | 
			
		||||
                WandererApp.Api.MapSystemSignature.by_system_id!(system.id)
 | 
			
		||||
                |> Enum.filter(fn s -> s.eve_id in removed_signatures_eve_ids end)
 | 
			
		||||
                |> Enum.each(fn s ->
 | 
			
		||||
                  s
 | 
			
		||||
                  |> Ash.destroy!()
 | 
			
		||||
                end)
 | 
			
		||||
 | 
			
		||||
            WandererApp.Api.MapSystemSignature.by_system_id!(system.id)
 | 
			
		||||
            |> Enum.filter(fn s -> s.eve_id in updated_signatures_eve_ids end)
 | 
			
		||||
            |> Enum.each(fn s ->
 | 
			
		||||
              updated = updated_signatures |> Enum.find(fn u -> u.eve_id == s.eve_id end)
 | 
			
		||||
                WandererApp.Api.MapSystemSignature.by_system_id!(system.id)
 | 
			
		||||
                |> Enum.filter(fn s -> s.eve_id in updated_signatures_eve_ids end)
 | 
			
		||||
                |> Enum.each(fn s ->
 | 
			
		||||
                  updated = updated_signatures |> Enum.find(fn u -> u.eve_id == s.eve_id end)
 | 
			
		||||
 | 
			
		||||
              if not is_nil(updated) do
 | 
			
		||||
                s
 | 
			
		||||
                |> WandererApp.Api.MapSystemSignature.update(updated)
 | 
			
		||||
              end
 | 
			
		||||
            end)
 | 
			
		||||
                  if not is_nil(updated) do
 | 
			
		||||
                    s
 | 
			
		||||
                    |> WandererApp.Api.MapSystemSignature.update(updated)
 | 
			
		||||
                  end
 | 
			
		||||
                end)
 | 
			
		||||
 | 
			
		||||
            added_signatures
 | 
			
		||||
            |> Enum.map(fn s ->
 | 
			
		||||
              s |> WandererApp.Api.MapSystemSignature.create!()
 | 
			
		||||
            end)
 | 
			
		||||
                added_signatures
 | 
			
		||||
                |> Enum.map(fn s ->
 | 
			
		||||
                  s |> WandererApp.Api.MapSystemSignature.create!()
 | 
			
		||||
                end)
 | 
			
		||||
 | 
			
		||||
            {:reply, %{signatures: _get_system_signatures(system.id)}, socket}
 | 
			
		||||
                {:reply, %{signatures: _get_system_signatures(system.id)}, socket}
 | 
			
		||||
              _ ->
 | 
			
		||||
                {:reply, %{signatures: []}, socket |> put_flash(
 | 
			
		||||
                  :error,
 | 
			
		||||
                  "You should enable tracking for at least one character to work with signatures."
 | 
			
		||||
                )}
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
          _ ->
 | 
			
		||||
            {:noreply, socket}
 | 
			
		||||
@@ -883,18 +958,26 @@ defmodule WandererAppWeb.MapLive do
 | 
			
		||||
  def handle_event(
 | 
			
		||||
        "update_system_position",
 | 
			
		||||
        position,
 | 
			
		||||
        socket
 | 
			
		||||
        %{assigns: %{has_tracked_characters?: has_tracked_characters?}} = socket
 | 
			
		||||
      ) do
 | 
			
		||||
    case _check_user_permissions(socket, :update_system) do
 | 
			
		||||
    case has_tracked_characters? do
 | 
			
		||||
      true ->
 | 
			
		||||
        socket
 | 
			
		||||
        |> map_id()
 | 
			
		||||
        |> _update_system_position(position)
 | 
			
		||||
        case _check_user_permissions(socket, :update_system) do
 | 
			
		||||
          true ->
 | 
			
		||||
            socket
 | 
			
		||||
            |> map_id()
 | 
			
		||||
            |> _update_system_position(position)
 | 
			
		||||
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
            {:noreply, socket}
 | 
			
		||||
 | 
			
		||||
          _ ->
 | 
			
		||||
            {:noreply, socket}
 | 
			
		||||
        end
 | 
			
		||||
      _ ->
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
        {:noreply, socket |> put_flash(
 | 
			
		||||
          :error,
 | 
			
		||||
          "You should enable tracking for at least one character to update system."
 | 
			
		||||
        )}
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
@@ -902,18 +985,26 @@ defmodule WandererAppWeb.MapLive do
 | 
			
		||||
  def handle_event(
 | 
			
		||||
        "update_system_positions",
 | 
			
		||||
        positions,
 | 
			
		||||
        socket
 | 
			
		||||
        %{assigns: %{has_tracked_characters?: has_tracked_characters?}} = socket
 | 
			
		||||
      ) do
 | 
			
		||||
    case _check_user_permissions(socket, :update_system) do
 | 
			
		||||
    case has_tracked_characters? do
 | 
			
		||||
      true ->
 | 
			
		||||
        socket
 | 
			
		||||
        |> map_id()
 | 
			
		||||
        |> _update_system_positions(positions)
 | 
			
		||||
        case _check_user_permissions(socket, :update_system) do
 | 
			
		||||
            true ->
 | 
			
		||||
              socket
 | 
			
		||||
              |> map_id()
 | 
			
		||||
              |> _update_system_positions(positions)
 | 
			
		||||
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
              {:noreply, socket}
 | 
			
		||||
 | 
			
		||||
            _ ->
 | 
			
		||||
              {:noreply, socket}
 | 
			
		||||
          end
 | 
			
		||||
      _ ->
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
        {:noreply, socket |> put_flash(
 | 
			
		||||
          :error,
 | 
			
		||||
          "You should enable tracking for at least one character to update systems."
 | 
			
		||||
        )}
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
@@ -921,58 +1012,76 @@ defmodule WandererAppWeb.MapLive do
 | 
			
		||||
  def handle_event(
 | 
			
		||||
        "delete_systems",
 | 
			
		||||
        solar_system_ids,
 | 
			
		||||
        %{assigns: %{current_user: current_user, tracked_character_ids: tracked_character_ids}} =
 | 
			
		||||
        %{assigns: %{current_user: current_user, tracked_character_ids: tracked_character_ids, has_tracked_characters?: has_tracked_characters?}} =
 | 
			
		||||
          socket
 | 
			
		||||
      ) do
 | 
			
		||||
    case _check_user_permissions(socket, :delete_system) do
 | 
			
		||||
    case has_tracked_characters? do
 | 
			
		||||
      true ->
 | 
			
		||||
        socket
 | 
			
		||||
        |> map_id()
 | 
			
		||||
        |> WandererApp.Map.Server.delete_systems(
 | 
			
		||||
          solar_system_ids |> Enum.map(&String.to_integer/1),
 | 
			
		||||
          current_user.id,
 | 
			
		||||
          tracked_character_ids |> List.first()
 | 
			
		||||
        )
 | 
			
		||||
        case _check_user_permissions(socket, :delete_system) do
 | 
			
		||||
          true ->
 | 
			
		||||
            socket
 | 
			
		||||
            |> map_id()
 | 
			
		||||
            |> WandererApp.Map.Server.delete_systems(
 | 
			
		||||
              solar_system_ids |> Enum.map(&String.to_integer/1),
 | 
			
		||||
              current_user.id,
 | 
			
		||||
              tracked_character_ids |> List.first()
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
            {:noreply, socket}
 | 
			
		||||
 | 
			
		||||
          _ ->
 | 
			
		||||
            {:noreply, socket}
 | 
			
		||||
        end
 | 
			
		||||
      _ ->
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
        {:noreply, socket |> put_flash(
 | 
			
		||||
          :error,
 | 
			
		||||
          "You should enable tracking for at least one character to delete systems."
 | 
			
		||||
        )}
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @impl true
 | 
			
		||||
  def handle_event(
 | 
			
		||||
        "manual_delete_connection",
 | 
			
		||||
        %{"source" => solar_system_source_id, "target" => solar_system_target_id} = _event,
 | 
			
		||||
        %{assigns: %{current_user: current_user, tracked_character_ids: tracked_character_ids}} =
 | 
			
		||||
        %{assigns: %{current_user: current_user, tracked_character_ids: tracked_character_ids, has_tracked_characters?: has_tracked_characters?}} =
 | 
			
		||||
          socket
 | 
			
		||||
      ) do
 | 
			
		||||
    case _check_user_permissions(socket, :delete_connection) do
 | 
			
		||||
    case has_tracked_characters? do
 | 
			
		||||
      true ->
 | 
			
		||||
        map_id =
 | 
			
		||||
          socket
 | 
			
		||||
          |> map_id()
 | 
			
		||||
        case _check_user_permissions(socket, :delete_connection) do
 | 
			
		||||
          true ->
 | 
			
		||||
            map_id =
 | 
			
		||||
              socket
 | 
			
		||||
              |> map_id()
 | 
			
		||||
 | 
			
		||||
        map_id
 | 
			
		||||
        |> WandererApp.Map.Server.delete_connection(%{
 | 
			
		||||
          solar_system_source_id: solar_system_source_id |> String.to_integer(),
 | 
			
		||||
          solar_system_target_id: solar_system_target_id |> String.to_integer()
 | 
			
		||||
        })
 | 
			
		||||
            map_id
 | 
			
		||||
            |> WandererApp.Map.Server.delete_connection(%{
 | 
			
		||||
              solar_system_source_id: solar_system_source_id |> String.to_integer(),
 | 
			
		||||
              solar_system_target_id: solar_system_target_id |> String.to_integer()
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
        :telemetry.execute([:wanderer_app, :map, :connection, :remove], %{count: 1}, %{
 | 
			
		||||
          character_id: tracked_character_ids |> List.first(),
 | 
			
		||||
          user_id: current_user.id,
 | 
			
		||||
          map_id: map_id,
 | 
			
		||||
          solar_system_source_id: "#{solar_system_source_id}" |> String.to_integer(),
 | 
			
		||||
          solar_system_target_id: "#{solar_system_target_id}" |> String.to_integer()
 | 
			
		||||
        })
 | 
			
		||||
            :telemetry.execute([:wanderer_app, :map, :connection, :remove], %{count: 1}, %{
 | 
			
		||||
              character_id: tracked_character_ids |> List.first(),
 | 
			
		||||
              user_id: current_user.id,
 | 
			
		||||
              map_id: map_id,
 | 
			
		||||
              solar_system_source_id: "#{solar_system_source_id}" |> String.to_integer(),
 | 
			
		||||
              solar_system_target_id: "#{solar_system_target_id}" |> String.to_integer()
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
            {:noreply, socket}
 | 
			
		||||
 | 
			
		||||
          _ ->
 | 
			
		||||
            {:noreply, socket}
 | 
			
		||||
        end
 | 
			
		||||
      _ ->
 | 
			
		||||
        {:noreply, socket}
 | 
			
		||||
        {:noreply, socket |> put_flash(
 | 
			
		||||
          :error,
 | 
			
		||||
          "You should enable tracking for at least one character to delete connection."
 | 
			
		||||
        )}
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @impl true
 | 
			
		||||
@@ -1061,6 +1170,7 @@ defmodule WandererAppWeb.MapLive do
 | 
			
		||||
  def handle_event("toggle_track", %{"character-id" => character_id}, socket) do
 | 
			
		||||
    map = socket.assigns.map
 | 
			
		||||
    character_settings = socket.assigns.character_settings
 | 
			
		||||
    current_user = socket.assigns.current_user
 | 
			
		||||
 | 
			
		||||
    socket =
 | 
			
		||||
      case character_settings |> Enum.find(&(&1.character_id == character_id)) do
 | 
			
		||||
@@ -1139,6 +1249,8 @@ defmodule WandererAppWeb.MapLive do
 | 
			
		||||
 | 
			
		||||
    {:noreply,
 | 
			
		||||
     socket
 | 
			
		||||
     |> assign(user_characters: user_character_eve_ids)
 | 
			
		||||
     |> assign(has_tracked_characters?: _has_tracked_characters?(user_character_eve_ids))
 | 
			
		||||
     |> assign(character_settings: character_settings)
 | 
			
		||||
     |> assign_async(:characters, fn ->
 | 
			
		||||
       {:ok, %{characters: characters}}
 | 
			
		||||
@@ -1275,6 +1387,15 @@ defmodule WandererAppWeb.MapLive do
 | 
			
		||||
              []
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          events =
 | 
			
		||||
            case map_characters |> Enum.empty?() do
 | 
			
		||||
              true ->
 | 
			
		||||
                events ++ [:empty_tracked_characters]
 | 
			
		||||
 | 
			
		||||
              _ ->
 | 
			
		||||
                events
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
        {:ok, characters_limit} = map_id |> WandererApp.Map.get_characters_limit()
 | 
			
		||||
 | 
			
		||||
        {:ok, present_character_ids} =
 | 
			
		||||
@@ -1480,6 +1601,7 @@ defmodule WandererAppWeb.MapLive do
 | 
			
		||||
          :character_eve_id,
 | 
			
		||||
          :name,
 | 
			
		||||
          :description,
 | 
			
		||||
          :custom_info,
 | 
			
		||||
          :kind,
 | 
			
		||||
          :group,
 | 
			
		||||
          :updated_at
 | 
			
		||||
@@ -1509,6 +1631,9 @@ defmodule WandererAppWeb.MapLive do
 | 
			
		||||
    {:ok, %{maps: maps |> Enum.sort_by(& &1.name, :asc) |> Enum.map(&map_map/1)}}
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  defp _has_tracked_characters?([]), do: false
 | 
			
		||||
  defp _has_tracked_characters?(_user_characters), do: true
 | 
			
		||||
 | 
			
		||||
  defp _update_system_positions(_map_id, []), do: :ok
 | 
			
		||||
 | 
			
		||||
  defp _update_system_positions(map_id, [position | rest]) do
 | 
			
		||||
@@ -1684,6 +1809,7 @@ defmodule WandererAppWeb.MapLive do
 | 
			
		||||
          eve_id: eve_id,
 | 
			
		||||
          name: name,
 | 
			
		||||
          description: Map.get(signature, "description"),
 | 
			
		||||
          custom_info: Map.get(signature, "custom_info"),
 | 
			
		||||
          kind: kind,
 | 
			
		||||
          group: group,
 | 
			
		||||
          character_eve_id: character_eve_id
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								mix.exs
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								mix.exs
									
									
									
									
									
								
							@@ -2,7 +2,7 @@ defmodule WandererApp.MixProject do
 | 
			
		||||
  use Mix.Project
 | 
			
		||||
 | 
			
		||||
  @source_url "https://github.com/wanderer-industries/wanderer"
 | 
			
		||||
  @version "1.0.7"
 | 
			
		||||
  @version "1.0.15"
 | 
			
		||||
 | 
			
		||||
  def project do
 | 
			
		||||
    [
 | 
			
		||||
@@ -56,7 +56,7 @@ defmodule WandererApp.MixProject do
 | 
			
		||||
      {:phoenix, "~> 1.7.12"},
 | 
			
		||||
      {:phoenix_ecto, "~> 4.6"},
 | 
			
		||||
      {:ecto_sql, "~> 3.10"},
 | 
			
		||||
      {:postgrex, ">= 0.0.0"},
 | 
			
		||||
      {:postgrex, "~> 0.19.1"},
 | 
			
		||||
      {:phoenix_html, "~> 4.0"},
 | 
			
		||||
      {:phoenix_live_reload, "~> 1.5.3", only: :dev},
 | 
			
		||||
      {:phoenix_live_view, "~> 0.20.17"},
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
 | 
			
		||||
export ERL_AFLAGS="-proto_dist inet6_tcp"
 | 
			
		||||
export ECTO_IPV6="true"
 | 
			
		||||
export RELEASE_DISTRIBUTION="name"
 | 
			
		||||
export RELEASE_NODE="${FLY_APP_NAME}-${FLY_IMAGE_REF##*-}@${FLY_PRIVATE_IP}"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user