mirror of
				https://github.com/wanderer-industries/wanderer
				synced 2025-11-04 00:14:52 +00:00 
			
		
		
		
	Compare commits
	
		
			3 Commits
		
	
	
		
			v1.32.6
			...
			19-add-map
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					d622e486f4 | ||
| 
						 | 
					81926633b0 | ||
| 
						 | 
					e4fe8fdc53 | 
@@ -60,15 +60,7 @@ config :dart_sass, :version, "1.54.5"
 | 
			
		||||
 | 
			
		||||
config :tailwind, :version, "3.2.7"
 | 
			
		||||
 | 
			
		||||
config :wanderer_app, WandererApp.PromEx,
 | 
			
		||||
  manual_metrics_start_delay: :no_delay,
 | 
			
		||||
  metrics_server: [
 | 
			
		||||
    port: 4021,
 | 
			
		||||
    path: "/metrics",
 | 
			
		||||
    protocol: :http,
 | 
			
		||||
    pool_size: 5,
 | 
			
		||||
    cowboy_opts: [ip: {0, 0, 0, 0}]
 | 
			
		||||
  ]
 | 
			
		||||
config :wanderer_app, WandererApp.PromEx, manual_metrics_start_delay: :no_delay
 | 
			
		||||
 | 
			
		||||
config :wanderer_app,
 | 
			
		||||
  grafana_datasource_id: "wanderer"
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ defmodule WandererApp.Api.Map do
 | 
			
		||||
    define(:update, action: :update)
 | 
			
		||||
    define(:update_acls, action: :update_acls)
 | 
			
		||||
    define(:update_hubs, action: :update_hubs)
 | 
			
		||||
    define(:update_options, action: :update_options)
 | 
			
		||||
    define(:assign_owner, action: :assign_owner)
 | 
			
		||||
    define(:mark_as_deleted, action: :mark_as_deleted)
 | 
			
		||||
 | 
			
		||||
@@ -112,6 +113,10 @@ defmodule WandererApp.Api.Map do
 | 
			
		||||
      accept [:hubs]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    update :update_options do
 | 
			
		||||
      accept [:options]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    update :mark_as_deleted do
 | 
			
		||||
      accept([])
 | 
			
		||||
 | 
			
		||||
@@ -167,6 +172,10 @@ defmodule WandererApp.Api.Map do
 | 
			
		||||
      allow_nil?(true)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    attribute :options, :string do
 | 
			
		||||
      allow_nil? true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    create_timestamp(:inserted_at)
 | 
			
		||||
    update_timestamp(:updated_at)
 | 
			
		||||
  end
 | 
			
		||||
 
 | 
			
		||||
@@ -52,6 +52,15 @@ defmodule WandererApp.Map do
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def get_map_options!(map) do
 | 
			
		||||
    map
 | 
			
		||||
    |> Map.get(:options)
 | 
			
		||||
    |> case do
 | 
			
		||||
        nil -> %{"layout" => "left_to_right"}
 | 
			
		||||
        options -> Jason.decode!(options)
 | 
			
		||||
      end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def update_map(map_id, map_update) do
 | 
			
		||||
    Cachex.get_and_update(:map_cache, map_id, fn map ->
 | 
			
		||||
      case map do
 | 
			
		||||
 
 | 
			
		||||
@@ -19,46 +19,47 @@ defmodule WandererApp.Map.PositionCalculator do
 | 
			
		||||
 | 
			
		||||
  def get_system_bounding_rect(_system), do: [{0, 0}, {0, 0}]
 | 
			
		||||
 | 
			
		||||
  def get_new_system_position(nil, rtree_name) do
 | 
			
		||||
    {:ok, {x, y}} = rtree_name |> _check_system_available_positions(@start_x, @start_y, 1)
 | 
			
		||||
  def get_new_system_position(nil, rtree_name, opts) do
 | 
			
		||||
    {:ok, {x, y}} = rtree_name |> check_system_available_positions(@start_x, @start_y, 1, opts)
 | 
			
		||||
    %{x: x, y: y}
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def get_new_system_position(
 | 
			
		||||
        %{position_x: start_x, position_y: start_y} = _old_system,
 | 
			
		||||
        rtree_name
 | 
			
		||||
        rtree_name,
 | 
			
		||||
        opts
 | 
			
		||||
      ) do
 | 
			
		||||
    {:ok, {x, y}} = rtree_name |> _check_system_available_positions(start_x, start_y, 1)
 | 
			
		||||
    {:ok, {x, y}} = rtree_name |> check_system_available_positions(start_x, start_y, 1, opts)
 | 
			
		||||
 | 
			
		||||
    %{x: x, y: y}
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  defp _check_system_available_positions(_rtree_name, _start_x, _start_y, 100) do
 | 
			
		||||
    {:ok, {@start_x, @start_y}}
 | 
			
		||||
  end
 | 
			
		||||
  defp check_system_available_positions(_rtree_name, _start_x, _start_y, 100, _opts),
 | 
			
		||||
    do: {:ok, {@start_x, @start_y}}
 | 
			
		||||
 | 
			
		||||
  defp _check_system_available_positions(rtree_name, start_x, start_y, level) do
 | 
			
		||||
    possible_positions = _get_available_positions(level, start_x, start_y)
 | 
			
		||||
  defp check_system_available_positions(rtree_name, start_x, start_y, level, opts) do
 | 
			
		||||
    possible_positions = get_available_positions(level, start_x, start_y, opts)
 | 
			
		||||
 | 
			
		||||
    case _get_available_position(possible_positions, rtree_name) do
 | 
			
		||||
    case get_available_position(possible_positions, rtree_name) do
 | 
			
		||||
      {:ok, nil} ->
 | 
			
		||||
        rtree_name |> _check_system_available_positions(start_x, start_y, level + 1)
 | 
			
		||||
        rtree_name |> check_system_available_positions(start_x, start_y, level + 1, opts)
 | 
			
		||||
 | 
			
		||||
      {:ok, position} ->
 | 
			
		||||
        {:ok, position}
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  defp _get_available_position([], _rtree_name), do: {:ok, nil}
 | 
			
		||||
  defp get_available_position([], _rtree_name), do: {:ok, nil}
 | 
			
		||||
 | 
			
		||||
  defp _get_available_position([position | rest], rtree_name) do
 | 
			
		||||
    if _is_available_position(position, rtree_name) do
 | 
			
		||||
  defp get_available_position([position | rest], rtree_name) do
 | 
			
		||||
    if is_available_position(position, rtree_name) do
 | 
			
		||||
      {:ok, position}
 | 
			
		||||
    else
 | 
			
		||||
      _get_available_position(rest, rtree_name)
 | 
			
		||||
      get_available_position(rest, rtree_name)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  defp _is_available_position({x, y} = _position, rtree_name) do
 | 
			
		||||
  defp is_available_position({x, y} = _position, rtree_name) do
 | 
			
		||||
    case DDRT.query(get_system_bounding_rect(%{position_x: x, position_y: y}), rtree_name) do
 | 
			
		||||
      {:ok, []} ->
 | 
			
		||||
        true
 | 
			
		||||
@@ -71,9 +72,10 @@ defmodule WandererApp.Map.PositionCalculator do
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def _get_available_positions(level, x, y), do: _adjusted_coordinates(1 + level * 2, x, y)
 | 
			
		||||
  def get_available_positions(level, x, y, opts),
 | 
			
		||||
    do: adjusted_coordinates(1 + level * 2, x, y, opts)
 | 
			
		||||
 | 
			
		||||
  defp _edge_coordinates(n) when n > 1 do
 | 
			
		||||
  defp edge_coordinates(n, opts) when n > 1 do
 | 
			
		||||
    min = -div(n, 2)
 | 
			
		||||
    max = div(n, 2)
 | 
			
		||||
    # Top edge
 | 
			
		||||
@@ -90,16 +92,20 @@ defmodule WandererApp.Map.PositionCalculator do
 | 
			
		||||
    |> Enum.uniq()
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  defp _sorted_edge_coordinates(n) when n > 1 do
 | 
			
		||||
    coordinates = _edge_coordinates(n)
 | 
			
		||||
    middle_right_index = div(n, 2)
 | 
			
		||||
  defp sorted_edge_coordinates(n, opts) when n > 1 do
 | 
			
		||||
    coordinates = edge_coordinates(n, opts)
 | 
			
		||||
    start_index = get_start_index(n, opts[:layout])
 | 
			
		||||
 | 
			
		||||
    Enum.slice(coordinates, middle_right_index, length(coordinates) - middle_right_index) ++
 | 
			
		||||
      Enum.slice(coordinates, 0, middle_right_index)
 | 
			
		||||
    Enum.slice(coordinates, start_index, length(coordinates) - start_index) ++
 | 
			
		||||
      Enum.slice(coordinates, 0, start_index)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  defp _adjusted_coordinates(n, start_x, start_y) when n > 1 do
 | 
			
		||||
    sorted_coords = _sorted_edge_coordinates(n)
 | 
			
		||||
  defp get_start_index(n, "left_to_right"), do: div(n, 2)
 | 
			
		||||
 | 
			
		||||
  defp get_start_index(n, "top_to_bottom"), do: div(n, 2) + n - 1
 | 
			
		||||
 | 
			
		||||
  defp adjusted_coordinates(n, start_x, start_y, opts) when n > 1 do
 | 
			
		||||
    sorted_coords = sorted_edge_coordinates(n, opts)
 | 
			
		||||
 | 
			
		||||
    Enum.map(sorted_coords, fn {x, y} ->
 | 
			
		||||
      {
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,8 @@ defmodule WandererApp.Map.Server.Impl do
 | 
			
		||||
  defstruct [
 | 
			
		||||
    :map_id,
 | 
			
		||||
    :rtree_name,
 | 
			
		||||
    map: nil
 | 
			
		||||
    map: nil,
 | 
			
		||||
    map_opts: []
 | 
			
		||||
  ]
 | 
			
		||||
 | 
			
		||||
  # @ccp1 -1
 | 
			
		||||
@@ -795,6 +796,9 @@ defmodule WandererApp.Map.Server.Impl do
 | 
			
		||||
    }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def handle_event({:options_updated, options}, %{map: map, map_id: map_id} = state),
 | 
			
		||||
    do: %{state | map_opts: [layout: options.layout]}
 | 
			
		||||
 | 
			
		||||
  def handle_event({ref, _result}, %{map_id: _map_id} = state) do
 | 
			
		||||
    Process.demonitor(ref, [:flush])
 | 
			
		||||
 | 
			
		||||
@@ -834,12 +838,12 @@ defmodule WandererApp.Map.Server.Impl do
 | 
			
		||||
         character_id,
 | 
			
		||||
         location,
 | 
			
		||||
         old_location,
 | 
			
		||||
         %{map: map, map_id: map_id, rtree_name: rtree_name} = _state
 | 
			
		||||
         %{map: map, map_id: map_id, rtree_name: rtree_name, map_opts: map_opts} = _state
 | 
			
		||||
       ) do
 | 
			
		||||
    case is_nil(old_location.solar_system_id) and
 | 
			
		||||
           _can_add_location(map.scope, location.solar_system_id) do
 | 
			
		||||
      true ->
 | 
			
		||||
        :ok = maybe_add_system(map_id, location, nil, rtree_name)
 | 
			
		||||
        :ok = maybe_add_system(map_id, location, nil, rtree_name, map_opts)
 | 
			
		||||
 | 
			
		||||
      _ ->
 | 
			
		||||
        case _is_connection_valid(
 | 
			
		||||
@@ -849,8 +853,8 @@ defmodule WandererApp.Map.Server.Impl do
 | 
			
		||||
             ) do
 | 
			
		||||
          true ->
 | 
			
		||||
            {:ok, character} = WandererApp.Character.get_character(character_id)
 | 
			
		||||
            :ok = maybe_add_system(map_id, location, old_location, rtree_name)
 | 
			
		||||
            :ok = maybe_add_system(map_id, old_location, location, rtree_name)
 | 
			
		||||
            :ok = maybe_add_system(map_id, location, old_location, rtree_name, map_opts)
 | 
			
		||||
            :ok = maybe_add_system(map_id, old_location, location, rtree_name, map_opts)
 | 
			
		||||
            :ok = maybe_add_connection(map_id, location, old_location, character)
 | 
			
		||||
 | 
			
		||||
          _ ->
 | 
			
		||||
@@ -1097,7 +1101,7 @@ defmodule WandererApp.Map.Server.Impl do
 | 
			
		||||
       end)}
 | 
			
		||||
 | 
			
		||||
  defp _add_system(
 | 
			
		||||
         %{map_id: map_id, rtree_name: rtree_name} = state,
 | 
			
		||||
         %{map_id: map_id, map_opts: map_opts, rtree_name: rtree_name} = state,
 | 
			
		||||
         %{
 | 
			
		||||
           solar_system_id: solar_system_id,
 | 
			
		||||
           coordinates: coordinates
 | 
			
		||||
@@ -1113,7 +1117,7 @@ defmodule WandererApp.Map.Server.Impl do
 | 
			
		||||
 | 
			
		||||
        _ ->
 | 
			
		||||
          %{x: x, y: y} =
 | 
			
		||||
            WandererApp.Map.PositionCalculator.get_new_system_position(nil, rtree_name)
 | 
			
		||||
            WandererApp.Map.PositionCalculator.get_new_system_position(nil, rtree_name, map_opts)
 | 
			
		||||
 | 
			
		||||
          %{"x" => x, "y" => y}
 | 
			
		||||
      end
 | 
			
		||||
@@ -1255,20 +1259,22 @@ defmodule WandererApp.Map.Server.Impl do
 | 
			
		||||
 | 
			
		||||
  defp _init_map(
 | 
			
		||||
         state,
 | 
			
		||||
         %{characters: characters} = map,
 | 
			
		||||
         %{characters: characters} = initial_map,
 | 
			
		||||
         subscription_settings,
 | 
			
		||||
         systems,
 | 
			
		||||
         connections
 | 
			
		||||
       ) do
 | 
			
		||||
    map =
 | 
			
		||||
      map
 | 
			
		||||
      initial_map
 | 
			
		||||
      |> WandererApp.Map.new()
 | 
			
		||||
      |> WandererApp.Map.update_subscription_settings!(subscription_settings)
 | 
			
		||||
      |> WandererApp.Map.add_systems!(systems)
 | 
			
		||||
      |> WandererApp.Map.add_connections!(connections)
 | 
			
		||||
      |> WandererApp.Map.add_characters!(characters)
 | 
			
		||||
 | 
			
		||||
    %{state | map: map}
 | 
			
		||||
    map_options = WandererApp.Map.get_map_options!(initial_map)
 | 
			
		||||
 | 
			
		||||
    %{state | map: map, map_opts: [layout: map_options |> Map.get("layout")]}
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  defp _init_map_systems(state, [] = _systems), do: state
 | 
			
		||||
@@ -1614,11 +1620,11 @@ defmodule WandererApp.Map.Server.Impl do
 | 
			
		||||
 | 
			
		||||
  defp maybe_add_connection(_map_id, _location, _old_location, _character), do: :ok
 | 
			
		||||
 | 
			
		||||
  defp maybe_add_system(map_id, location, old_location, rtree_name)
 | 
			
		||||
  defp maybe_add_system(map_id, location, old_location, rtree_name, opts)
 | 
			
		||||
       when not is_nil(location) do
 | 
			
		||||
    case WandererApp.Map.check_location(map_id, location) do
 | 
			
		||||
      {:ok, location} ->
 | 
			
		||||
        {:ok, position} = calc_new_system_position(map_id, old_location, rtree_name)
 | 
			
		||||
        {:ok, position} = calc_new_system_position(map_id, old_location, rtree_name, opts)
 | 
			
		||||
 | 
			
		||||
        case WandererApp.MapSystemRepo.get_by_map_and_solar_system_id(
 | 
			
		||||
               map_id,
 | 
			
		||||
@@ -1688,14 +1694,14 @@ defmodule WandererApp.Map.Server.Impl do
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  defp maybe_add_system(_map_id, _location, _old_location, _rtree_name), do: :ok
 | 
			
		||||
  defp maybe_add_system(_map_id, _location, _old_location, _rtree_name, _opts), do: :ok
 | 
			
		||||
 | 
			
		||||
  defp calc_new_system_position(map_id, old_location, rtree_name) do
 | 
			
		||||
  defp calc_new_system_position(map_id, old_location, rtree_name, opts),
 | 
			
		||||
    do:
 | 
			
		||||
    {:ok,
 | 
			
		||||
     map_id
 | 
			
		||||
     |> WandererApp.Map.find_system_by_location(old_location)
 | 
			
		||||
     |> WandererApp.Map.PositionCalculator.get_new_system_position(rtree_name)}
 | 
			
		||||
  end
 | 
			
		||||
     |> WandererApp.Map.PositionCalculator.get_new_system_position(rtree_name, opts)}
 | 
			
		||||
 | 
			
		||||
  defp _broadcast_acl_updates(
 | 
			
		||||
         {:ok,
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,8 @@ defmodule WandererAppWeb.MapsLive do
 | 
			
		||||
 | 
			
		||||
  alias BetterNumber, as: Number
 | 
			
		||||
 | 
			
		||||
  @pubsub_client Application.compile_env(:wanderer_app, :pubsub_client)
 | 
			
		||||
 | 
			
		||||
  @impl true
 | 
			
		||||
  def mount(_params, %{"user_id" => user_id} = _session, socket) when not is_nil(user_id) do
 | 
			
		||||
    {:ok, active_characters} = WandererApp.Api.Character.active_by_user(%{user_id: user_id})
 | 
			
		||||
@@ -112,6 +114,13 @@ defmodule WandererAppWeb.MapsLive do
 | 
			
		||||
      "auto_renew?" => true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    options_form =
 | 
			
		||||
      map.options
 | 
			
		||||
      |> case do
 | 
			
		||||
        nil -> %{"layout" => "left_to_right"}
 | 
			
		||||
        options -> Jason.decode!(options)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
    {:ok, estimated_price, discount} =
 | 
			
		||||
      WandererApp.Map.SubscriptionManager.estimate_price(subscription_form, false)
 | 
			
		||||
 | 
			
		||||
@@ -130,6 +139,7 @@ defmodule WandererAppWeb.MapsLive do
 | 
			
		||||
      active_settings_tab: "general",
 | 
			
		||||
      is_adding_subscription?: false,
 | 
			
		||||
      selected_subscription: nil,
 | 
			
		||||
      options_form: options_form |> to_form(),
 | 
			
		||||
      map_subscriptions: map_subscriptions,
 | 
			
		||||
      subscription_form: subscription_form |> to_form(),
 | 
			
		||||
      estimated_price: estimated_price,
 | 
			
		||||
@@ -142,6 +152,10 @@ defmodule WandererAppWeb.MapsLive do
 | 
			
		||||
        {"3 Months", "3"},
 | 
			
		||||
        {"6 Months", "6"},
 | 
			
		||||
        {"1 Year", "12"}
 | 
			
		||||
      ],
 | 
			
		||||
      layout_options: [
 | 
			
		||||
        {"Left To Right", "left_to_right"},
 | 
			
		||||
        {"Top To Bottom", "top_to_bottom"}
 | 
			
		||||
      ]
 | 
			
		||||
    )
 | 
			
		||||
    |> allow_upload(:settings,
 | 
			
		||||
@@ -653,6 +667,28 @@ defmodule WandererAppWeb.MapsLive do
 | 
			
		||||
     |> push_patch(to: ~p"/maps")}
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def handle_event(
 | 
			
		||||
        "update_options",
 | 
			
		||||
        %{
 | 
			
		||||
          "layout" => layout
 | 
			
		||||
        } = options_form,
 | 
			
		||||
        %{assigns: %{map_id: map_id, map: map, current_user: current_user}} = socket
 | 
			
		||||
      ) do
 | 
			
		||||
    options = %{layout: layout}
 | 
			
		||||
 | 
			
		||||
    updated_map =
 | 
			
		||||
      map
 | 
			
		||||
      |> WandererApp.Api.Map.update_options!(%{options: Jason.encode!(options)})
 | 
			
		||||
 | 
			
		||||
    @pubsub_client.broadcast(
 | 
			
		||||
      WandererApp.PubSub,
 | 
			
		||||
      "maps:#{map_id}",
 | 
			
		||||
      {:options_updated, options}
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    {:noreply, socket |> assign(map: updated_map, options_form: options_form)}
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @impl true
 | 
			
		||||
  def handle_event("noop", _, socket) do
 | 
			
		||||
    {:noreply, socket}
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,6 @@
 | 
			
		||||
          >
 | 
			
		||||
            <figure class="absolute z-10 h-200 avatar w-full h-full">
 | 
			
		||||
              <img :if={map.scope === :all} class="absolute h-200" src="/images/all_back.webp" />
 | 
			
		||||
 | 
			
		||||
              <img
 | 
			
		||||
                :if={map.scope === :wormholes}
 | 
			
		||||
                class="absolute h-200"
 | 
			
		||||
@@ -190,7 +189,6 @@
 | 
			
		||||
>
 | 
			
		||||
  <div role="tablist" class="tabs tabs-bordered">
 | 
			
		||||
    <a
 | 
			
		||||
      :if={@map_subscriptions_enabled?}
 | 
			
		||||
      role="tab"
 | 
			
		||||
      phx-click="change_settings_tab"
 | 
			
		||||
      phx-value-tab="general"
 | 
			
		||||
@@ -201,6 +199,17 @@
 | 
			
		||||
    >
 | 
			
		||||
      <.icon name="hero-wrench-screwdriver-solid" class="w-4 h-4" /> General
 | 
			
		||||
    </a>
 | 
			
		||||
    <a
 | 
			
		||||
      role="tab"
 | 
			
		||||
      phx-click="change_settings_tab"
 | 
			
		||||
      phx-value-tab="import"
 | 
			
		||||
      class={[
 | 
			
		||||
        "tab",
 | 
			
		||||
        classes("tab-active": @active_settings_tab == "import")
 | 
			
		||||
      ]}
 | 
			
		||||
    >
 | 
			
		||||
      <.icon name="hero-wrench-screwdriver-solid" class="w-4 h-4" /> Import/Export
 | 
			
		||||
    </a>
 | 
			
		||||
    <a
 | 
			
		||||
      :if={@map_subscriptions_enabled?}
 | 
			
		||||
      role="tab"
 | 
			
		||||
@@ -227,6 +236,27 @@
 | 
			
		||||
    </a>
 | 
			
		||||
  </div>
 | 
			
		||||
  <.header :if={@active_settings_tab == "general"} class="bordered border-1 border-zinc-800">
 | 
			
		||||
    <:actions>
 | 
			
		||||
      <.form
 | 
			
		||||
        :let={f}
 | 
			
		||||
        :if={assigns |> Map.get(:options_form, false)}
 | 
			
		||||
        for={@options_form}
 | 
			
		||||
        phx-change="update_options"
 | 
			
		||||
      >
 | 
			
		||||
        <div class="stat-title">Map systems layout</div>
 | 
			
		||||
        <div class="stat-value text-white">
 | 
			
		||||
          <.input
 | 
			
		||||
            type="select"
 | 
			
		||||
            field={f[:layout]}
 | 
			
		||||
            class="p-dropdown p-component p-inputwrapper"
 | 
			
		||||
            placeholder="Map default layout"
 | 
			
		||||
            options={@layout_options}
 | 
			
		||||
          />
 | 
			
		||||
        </div>
 | 
			
		||||
      </.form>
 | 
			
		||||
    </:actions>
 | 
			
		||||
  </.header>
 | 
			
		||||
  <.header :if={@active_settings_tab == "import"} class="bordered border-1 border-zinc-800">
 | 
			
		||||
    Import/Export Map Settings
 | 
			
		||||
    <:actions>
 | 
			
		||||
      <.form :if={assigns |> Map.get(:import_form, false)} for={@import_form} phx-change="import">
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								priv/repo/migrations/20241006092351_add_map_options.exs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								priv/repo/migrations/20241006092351_add_map_options.exs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
defmodule WandererApp.Repo.Migrations.AddMapOptions do
 | 
			
		||||
  @moduledoc """
 | 
			
		||||
  Updates resources based on their most recent snapshots.
 | 
			
		||||
 | 
			
		||||
  This file was autogenerated with `mix ash_postgres.generate_migrations`
 | 
			
		||||
  """
 | 
			
		||||
 | 
			
		||||
  use Ecto.Migration
 | 
			
		||||
 | 
			
		||||
  def up do
 | 
			
		||||
    alter table(:maps_v1) do
 | 
			
		||||
      add :options, :text
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def down do
 | 
			
		||||
    alter table(:maps_v1) do
 | 
			
		||||
      remove :options
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										186
									
								
								priv/resource_snapshots/repo/maps_v1/20241006092351.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								priv/resource_snapshots/repo/maps_v1/20241006092351.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,186 @@
 | 
			
		||||
{
 | 
			
		||||
  "attributes": [
 | 
			
		||||
    {
 | 
			
		||||
      "allow_nil?": false,
 | 
			
		||||
      "default": "fragment(\"gen_random_uuid()\")",
 | 
			
		||||
      "generated?": false,
 | 
			
		||||
      "primary_key?": true,
 | 
			
		||||
      "references": null,
 | 
			
		||||
      "size": null,
 | 
			
		||||
      "source": "id",
 | 
			
		||||
      "type": "uuid"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "allow_nil?": false,
 | 
			
		||||
      "default": "nil",
 | 
			
		||||
      "generated?": false,
 | 
			
		||||
      "primary_key?": false,
 | 
			
		||||
      "references": null,
 | 
			
		||||
      "size": null,
 | 
			
		||||
      "source": "name",
 | 
			
		||||
      "type": "text"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "allow_nil?": false,
 | 
			
		||||
      "default": "nil",
 | 
			
		||||
      "generated?": false,
 | 
			
		||||
      "primary_key?": false,
 | 
			
		||||
      "references": null,
 | 
			
		||||
      "size": null,
 | 
			
		||||
      "source": "slug",
 | 
			
		||||
      "type": "text"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "allow_nil?": true,
 | 
			
		||||
      "default": "nil",
 | 
			
		||||
      "generated?": false,
 | 
			
		||||
      "primary_key?": false,
 | 
			
		||||
      "references": null,
 | 
			
		||||
      "size": null,
 | 
			
		||||
      "source": "description",
 | 
			
		||||
      "type": "text"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "allow_nil?": true,
 | 
			
		||||
      "default": "nil",
 | 
			
		||||
      "generated?": false,
 | 
			
		||||
      "primary_key?": false,
 | 
			
		||||
      "references": null,
 | 
			
		||||
      "size": null,
 | 
			
		||||
      "source": "personal_note",
 | 
			
		||||
      "type": "text"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "allow_nil?": true,
 | 
			
		||||
      "default": "[]",
 | 
			
		||||
      "generated?": false,
 | 
			
		||||
      "primary_key?": false,
 | 
			
		||||
      "references": null,
 | 
			
		||||
      "size": null,
 | 
			
		||||
      "source": "hubs",
 | 
			
		||||
      "type": [
 | 
			
		||||
        "array",
 | 
			
		||||
        "text"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "allow_nil?": false,
 | 
			
		||||
      "default": "\"wormholes\"",
 | 
			
		||||
      "generated?": false,
 | 
			
		||||
      "primary_key?": false,
 | 
			
		||||
      "references": null,
 | 
			
		||||
      "size": null,
 | 
			
		||||
      "source": "scope",
 | 
			
		||||
      "type": "text"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "allow_nil?": true,
 | 
			
		||||
      "default": "false",
 | 
			
		||||
      "generated?": false,
 | 
			
		||||
      "primary_key?": false,
 | 
			
		||||
      "references": null,
 | 
			
		||||
      "size": null,
 | 
			
		||||
      "source": "deleted",
 | 
			
		||||
      "type": "boolean"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "allow_nil?": true,
 | 
			
		||||
      "default": "false",
 | 
			
		||||
      "generated?": false,
 | 
			
		||||
      "primary_key?": false,
 | 
			
		||||
      "references": null,
 | 
			
		||||
      "size": null,
 | 
			
		||||
      "source": "only_tracked_characters",
 | 
			
		||||
      "type": "boolean"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "allow_nil?": true,
 | 
			
		||||
      "default": "nil",
 | 
			
		||||
      "generated?": false,
 | 
			
		||||
      "primary_key?": false,
 | 
			
		||||
      "references": null,
 | 
			
		||||
      "size": null,
 | 
			
		||||
      "source": "options",
 | 
			
		||||
      "type": "text"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "allow_nil?": false,
 | 
			
		||||
      "default": "fragment(\"(now() AT TIME ZONE 'utc')\")",
 | 
			
		||||
      "generated?": false,
 | 
			
		||||
      "primary_key?": false,
 | 
			
		||||
      "references": null,
 | 
			
		||||
      "size": null,
 | 
			
		||||
      "source": "inserted_at",
 | 
			
		||||
      "type": "utc_datetime_usec"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "allow_nil?": false,
 | 
			
		||||
      "default": "fragment(\"(now() AT TIME ZONE 'utc')\")",
 | 
			
		||||
      "generated?": false,
 | 
			
		||||
      "primary_key?": false,
 | 
			
		||||
      "references": null,
 | 
			
		||||
      "size": null,
 | 
			
		||||
      "source": "updated_at",
 | 
			
		||||
      "type": "utc_datetime_usec"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "allow_nil?": true,
 | 
			
		||||
      "default": "nil",
 | 
			
		||||
      "generated?": false,
 | 
			
		||||
      "primary_key?": false,
 | 
			
		||||
      "references": {
 | 
			
		||||
        "deferrable": false,
 | 
			
		||||
        "destination_attribute": "id",
 | 
			
		||||
        "destination_attribute_default": null,
 | 
			
		||||
        "destination_attribute_generated": null,
 | 
			
		||||
        "index?": false,
 | 
			
		||||
        "match_type": null,
 | 
			
		||||
        "match_with": null,
 | 
			
		||||
        "multitenancy": {
 | 
			
		||||
          "attribute": null,
 | 
			
		||||
          "global": null,
 | 
			
		||||
          "strategy": null
 | 
			
		||||
        },
 | 
			
		||||
        "name": "maps_v1_owner_id_fkey",
 | 
			
		||||
        "on_delete": null,
 | 
			
		||||
        "on_update": null,
 | 
			
		||||
        "primary_key?": true,
 | 
			
		||||
        "schema": "public",
 | 
			
		||||
        "table": "character_v1"
 | 
			
		||||
      },
 | 
			
		||||
      "size": null,
 | 
			
		||||
      "source": "owner_id",
 | 
			
		||||
      "type": "uuid"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "base_filter": null,
 | 
			
		||||
  "check_constraints": [],
 | 
			
		||||
  "custom_indexes": [],
 | 
			
		||||
  "custom_statements": [],
 | 
			
		||||
  "has_create_action": true,
 | 
			
		||||
  "hash": "E5FC6B5F1B9AD5E23163494C7C93A8002F9C812AFC7A26A8C33A344877086A03",
 | 
			
		||||
  "identities": [
 | 
			
		||||
    {
 | 
			
		||||
      "all_tenants?": false,
 | 
			
		||||
      "base_filter": null,
 | 
			
		||||
      "index_name": "maps_v1_unique_slug_index",
 | 
			
		||||
      "keys": [
 | 
			
		||||
        {
 | 
			
		||||
          "type": "atom",
 | 
			
		||||
          "value": "slug"
 | 
			
		||||
        }
 | 
			
		||||
      ],
 | 
			
		||||
      "name": "unique_slug",
 | 
			
		||||
      "nils_distinct?": true,
 | 
			
		||||
      "where": null
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "multitenancy": {
 | 
			
		||||
    "attribute": null,
 | 
			
		||||
    "global": null,
 | 
			
		||||
    "strategy": null
 | 
			
		||||
  },
 | 
			
		||||
  "repo": "Elixir.WandererApp.Repo",
 | 
			
		||||
  "schema": null,
 | 
			
		||||
  "table": "maps_v1"
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user