Compare commits

...

3 Commits

Author SHA1 Message Date
CI
8f20cd9863 chore: release version v1.6.0 2024-10-13 08:58:05 +00:00
Dmitry Popov
4ed0e85680 Merge branch 'main' of github.com:wanderer-industries/wanderer 2024-10-13 12:57:37 +04:00
Dmitry Popov
8ce9eb9955 feat(Map): Link signature on splash 2024-10-13 12:57:33 +04:00
30 changed files with 591 additions and 66 deletions

View File

@@ -2,6 +2,15 @@
<!-- changelog -->
## [v1.6.0](https://github.com/wanderer-industries/wanderer/compare/v1.5.0...v1.6.0) (2024-10-13)
### Features:
* Map: Link signature on splash
## [v1.5.0](https://github.com/wanderer-industries/wanderer/compare/v1.4.0...v1.5.0) (2024-10-11)

View File

@@ -118,6 +118,10 @@ export const useMapHandlers = (ref: ForwardedRef<MapHandlers>, onSelectionChange
// do nothing here
break;
case Commands.linkSignatureToSystem:
// do nothing here
break;
default:
console.warn(`Map handlers: Unknown command: ${type}`, data);
break;

View File

@@ -0,0 +1,70 @@
import { useCallback, useRef } from 'react';
import { Dialog } from 'primereact/dialog';
import { OutCommand } from '@/hooks/Mapper/types/mapHandlers.ts';
import { SystemSignature } from '@/hooks/Mapper/types';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { CommandLinkSignatureToSystem } from '@/hooks/Mapper/types';
import { SystemSignaturesContent } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignaturesContent';
import {
Setting,
COSMIC_SIGNATURE,
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignatureSettingsDialog';
interface SystemLinkSignatureDialogProps {
data: CommandLinkSignatureToSystem;
setVisible: (visible: boolean) => void;
}
const signatureSettings: Setting[] = [{ key: COSMIC_SIGNATURE, name: 'Show Cosmic Signatures', value: true }];
export const SystemLinkSignatureDialog = ({ data, setVisible }: SystemLinkSignatureDialogProps) => {
const { outCommand } = useMapRootState();
console.log(data);
const ref = useRef({ outCommand });
ref.current = { outCommand };
const handleHide = useCallback(() => {
setVisible(false);
}, [setVisible]);
const handleSelect = useCallback(
(signatures: SystemSignature[]) => {
if (!signatures.length) {
return;
}
const { outCommand } = ref.current;
outCommand({
type: OutCommand.linkSignatureToSystem,
data: {
...data,
signature_eve_id: signatures[0].eve_id,
},
});
setVisible(false);
},
[setVisible],
);
return (
<Dialog
header="Select signature to link"
visible
draggable={false}
style={{ width: '500px' }}
onHide={handleHide}
contentClassName="!p-0"
>
<SystemSignaturesContent
systemId={`${data.solar_system_source}`}
settings={signatureSettings}
onSelect={handleSelect}
selectable={true}
/>
</Dialog>
);
};

View File

@@ -0,0 +1 @@
export * from './SystemLinkSignatureDialog';

View File

@@ -2,3 +2,4 @@ export * from './Widget';
export * from './WidgetsGrid';
export * from './SystemSettingsDialog';
export * from './SystemCustomLabelDialog';
export * from './SystemLinkSignatureDialog';

View File

@@ -5,6 +5,14 @@ import { Checkbox } from 'primereact/checkbox';
export type Setting = { key: string; name: string; value: boolean };
export const COSMIC_SIGNATURE = 'Cosmic Signature';
export const COSMIC_ANOMALY = 'Cosmic Anomaly';
export const DEPLOYABLE = 'Deployable';
export const STRUCTURE = 'Structure';
export const STARBASE = 'Starbase';
export const SHIP = 'Ship';
export const DRONE = 'Drone';
interface SystemSignatureSettingsDialogProps {
settings: Setting[];
onSave: (settings: Setting[]) => void;

View File

@@ -1,7 +1,17 @@
import { Widget } from '@/hooks/Mapper/components/mapInterface/components';
import { InfoDrawer, LayoutEventBlocker, TooltipPosition, WdImgButton } from '@/hooks/Mapper/components/ui-kit';
import { SystemSignaturesContent } from './SystemSignaturesContent';
import { Setting, SystemSignatureSettingsDialog } from './SystemSignatureSettingsDialog';
import {
Setting,
SystemSignatureSettingsDialog,
COSMIC_SIGNATURE,
COSMIC_ANOMALY,
DEPLOYABLE,
STRUCTURE,
STARBASE,
SHIP,
DRONE,
} from './SystemSignatureSettingsDialog';
import React, { useCallback, useEffect, useState } from 'react';
@@ -9,14 +19,6 @@ import { PrimeIcons } from 'primereact/api';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
export const COSMIC_SIGNATURE = 'Cosmic Signature';
export const COSMIC_ANOMALY = 'Cosmic Anomaly';
export const DEPLOYABLE = 'Deployable';
export const STRUCTURE = 'Structure';
export const STARBASE = 'Starbase';
export const SHIP = 'Ship';
export const DRONE = 'Drone';
const settings: Setting[] = [
{ key: COSMIC_ANOMALY, name: 'Show Anomalies', value: true },
{ key: COSMIC_SIGNATURE, name: 'Show Cosmic Signatures', value: true },

View File

@@ -24,6 +24,7 @@ import {
renderIcon,
renderName,
renderTimeLeft,
renderLinkedSystem,
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/renders';
// import { PrimeIcons } from 'primereact/api';
import useLocalStorageState from 'use-local-storage-state';
@@ -41,8 +42,10 @@ const SORT_DEFAULT_VALUES: SystemSignaturesSortSettings = {
interface SystemSignaturesContentProps {
systemId: string;
settings: Setting[];
selectable?: boolean;
onSelect?: (signatures: SystemSignature[]) => void;
}
export const SystemSignaturesContent = ({ systemId, settings }: SystemSignaturesContentProps) => {
export const SystemSignaturesContent = ({ systemId, settings, selectable, onSelect }: SystemSignaturesContentProps) => {
const { outCommand } = useMapRootState();
const [signatures, setSignatures, signaturesRef] = useRefState<SystemSignature[]>([]);
@@ -92,25 +95,25 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures
setSignatures(signatures);
}, [outCommand, systemId]);
const updateSignatures = useCallback(
async (newSignatures: SystemSignature[], updateOnly: boolean) => {
const { added, updated, removed } = getActualSigs(signaturesRef.current, newSignatures, updateOnly);
// const updateSignatures = useCallback(
// async (newSignatures: SystemSignature[], updateOnly: boolean) => {
// const { added, updated, removed } = getActualSigs(signaturesRef.current, newSignatures, updateOnly);
const { signatures: updatedSignatures } = await outCommand({
type: OutCommand.updateSignatures,
data: {
system_id: systemId,
added,
updated,
removed,
},
});
// const { signatures: updatedSignatures } = await outCommand({
// type: OutCommand.updateSignatures,
// data: {
// system_id: systemId,
// added,
// updated,
// removed,
// },
// });
setSignatures(() => updatedSignatures);
setSelectedSignatures([]);
},
[outCommand, systemId],
);
// setSignatures(() => updatedSignatures);
// setSelectedSignatures([]);
// },
// [outCommand, systemId],
// );
const handleUpdateSignatures = useCallback(
async (newSignatures: SystemSignature[], updateOnly: boolean) => {
@@ -133,6 +136,9 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures
);
const handleDeleteSelected = useCallback(async () => {
if (selectable) {
return;
}
if (selectedSignatures.length === 0) {
return;
}
@@ -141,7 +147,7 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures
signatures.filter(x => !selectedSignaturesEveIds.includes(x.eve_id)),
false,
);
}, [handleUpdateSignatures, signatures, selectedSignatures]);
}, [handleUpdateSignatures, selectable, signatures, selectedSignatures]);
const handleSelectAll = useCallback(() => {
setSelectedSignatures(signatures);
@@ -157,11 +163,20 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures
setAskUser(false);
}, [parsedSignatures, handleUpdateSignatures]);
const handleSelectSignatures = useCallback(e => {
setSelectedSignatures(e.value);
onSelect?.(e.value);
}, []);
useHotkey(true, ['a'], handleSelectAll);
useHotkey(false, ['Backspace', 'Delete'], handleDeleteSelected);
useEffect(() => {
if (selectable) {
return;
}
if (!clipboardContent) {
return;
}
@@ -179,7 +194,7 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures
setParsedSignatures(newSignatures);
setAskUser(true);
}
}, [clipboardContent]);
}, [clipboardContent, selectable]);
useEffect(() => {
if (!systemId) {
@@ -240,10 +255,10 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures
className={classes.Table}
value={filteredSignatures}
size="small"
selectionMode="multiple"
// selectionMode={selectable ? 'multiple' : 'single'}
selection={selectedSignatures}
metaKeySelection
onSelectionChange={e => setSelectedSignatures(e.value)}
onSelectionChange={handleSelectSignatures}
dataKey="eve_id"
tableClassName="w-full select-none"
resizableColumns={false}
@@ -297,6 +312,18 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures
hidden={compact || medium}
sortable
></Column>
{!selectable && (
<Column
field="linked_system"
header="Linked System"
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
body={renderLinkedSystem}
style={{ maxWidth: nameColumnWidth }}
hidden={compact}
sortable
></Column>
)}
<Column
field="updated_at"
header="Updated"

View File

@@ -1,3 +1,4 @@
export * from './renderIcon';
export * from './renderName';
export * from './renderTimeLeft';
export * from './renderLinkedSystem';

View File

@@ -0,0 +1,20 @@
import clsx from 'clsx';
import { SystemSignature } from '@/hooks/Mapper/types';
import { SystemViewStandalone } from '@/hooks/Mapper/components/ui-kit';
export const renderLinkedSystem = (row: SystemSignature) => {
if (!row.linked_system) {
return null;
}
return (
<span title={row.linked_system?.solar_system_name}>
<SystemViewStandalone
className={clsx('select-none text-center cursor-context-menu')}
hideRegion
{...row.linked_system}
/>
</span>
);
};

View File

@@ -5,13 +5,20 @@ import { MapRootData, useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { OnMapSelectionChange } from '@/hooks/Mapper/components/map/map.types.ts';
import isEqual from 'lodash.isequal';
import { ContextMenuSystem, useContextMenuSystemHandlers } from '@/hooks/Mapper/components/contexts';
import { SystemCustomLabelDialog, SystemSettingsDialog } from '@/hooks/Mapper/components/mapInterface/components';
import {
SystemCustomLabelDialog,
SystemSettingsDialog,
SystemLinkSignatureDialog,
} from '@/hooks/Mapper/components/mapInterface/components';
import classes from './MapWrapper.module.scss';
import { Connections } from '@/hooks/Mapper/components/mapRootContent/components/Connections';
import { ContextMenuSystemMultiple, useContextMenuSystemMultipleHandlers } from '../contexts/ContextMenuSystemMultiple';
import { getSystemById } from '@/hooks/Mapper/helpers';
import { Node } from 'reactflow';
import { Commands } from '@/hooks/Mapper/types/mapHandlers.ts';
import { useMapEventListener } from '@/hooks/Mapper/events';
import { STORED_INTERFACE_DEFAULT_VALUES } from '@/hooks/Mapper/mapRootProvider/MapRootProvider';
interface MapWrapperProps {
@@ -53,6 +60,7 @@ export const MapWrapper = ({ refn }: MapWrapperProps) => {
);
const [openSettings, setOpenSettings] = useState<string | null>(null);
const [openLinkSignatures, setOpenLinkSignatures] = useState<any | null>(null);
const [openCustomLabel, setOpenCustomLabel] = useState<string | null>(null);
const handleCommand: OutCommandHandler = useCallback(
event => {
@@ -60,6 +68,9 @@ export const MapWrapper = ({ refn }: MapWrapperProps) => {
case OutCommand.openSettings:
setOpenSettings(event.data.system_id);
break;
case OutCommand.linkSignatureToSystem:
setOpenLinkSignatures(event.data);
break;
default:
return outCommand(event);
}
@@ -88,6 +99,14 @@ export const MapWrapper = ({ refn }: MapWrapperProps) => {
const handleConnectionDbClick = useCallback((e: SolarSystemConnection) => setSelectedConnection(e), []);
useMapEventListener(event => {
switch (event.name) {
case Commands.linkSignatureToSystem:
setOpenLinkSignatures(event.data);
return true;
}
});
return (
<>
<Map
@@ -103,19 +122,15 @@ export const MapWrapper = ({ refn }: MapWrapperProps) => {
/>
{openSettings != null && (
<SystemSettingsDialog
systemId={openSettings}
visible={openSettings != null}
setVisible={() => setOpenSettings(null)}
/>
<SystemSettingsDialog systemId={openSettings} visible setVisible={() => setOpenSettings(null)} />
)}
{openCustomLabel != null && (
<SystemCustomLabelDialog
systemId={openCustomLabel}
visible={openCustomLabel != null}
setVisible={() => setOpenCustomLabel(null)}
/>
<SystemCustomLabelDialog systemId={openCustomLabel} visible setVisible={() => setOpenCustomLabel(null)} />
)}
{openLinkSignatures != null && (
<SystemLinkSignatureDialog data={openLinkSignatures} setVisible={() => setOpenLinkSignatures(null)} />
)}
<Connections selectedConnection={selectedConnection} onHide={() => setSelectedConnection(null)} />

View File

@@ -0,0 +1,13 @@
import { createEvent } from 'react-event-hook';
export interface MapEvent {
name: string;
data: {
solar_system_source: number;
solar_system_target: number;
};
}
const { useMapEventListener, emitMapEvent } = createEvent('map-event')<MapEvent>();
export { useMapEventListener, emitMapEvent };

View File

@@ -1,4 +1,4 @@
import { COSMIC_SIGNATURE } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures';
import { COSMIC_SIGNATURE } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignatureSettingsDialog';
import { SystemSignature } from '@/hooks/Mapper/types';
export const parseSignatures = (value: string, availableKeys: string[]): SystemSignature[] => {

View File

@@ -27,6 +27,8 @@ import {
useRoutes,
} from './api';
import { emitMapEvent } from '@/hooks/Mapper/events';
export const useMapRootHandlers = (ref: ForwardedRef<MapHandlers>) => {
const mapInit = useMapInit();
const { addSystems, removeSystems, updateSystems } = useCommandsSystems();
@@ -93,6 +95,10 @@ export const useMapRootHandlers = (ref: ForwardedRef<MapHandlers>) => {
// do nothing here
break;
case Commands.linkSignatureToSystem:
emitMapEvent({ name: Commands.linkSignatureToSystem, data });
break;
case Commands.killsUpdated:
// do nothing here
break;

View File

@@ -23,6 +23,7 @@ export enum Commands {
routes = 'routes',
centerSystem = 'center_system',
selectSystem = 'select_system',
linkSignatureToSystem = 'link_signature_to_system',
}
export type Command =
@@ -42,7 +43,8 @@ export type Command =
| Commands.killsUpdated
| Commands.routes
| Commands.selectSystem
| Commands.centerSystem;
| Commands.centerSystem
| Commands.linkSignatureToSystem;
export type CommandInit = {
systems: SolarSystemRawType[];
@@ -75,6 +77,11 @@ export type CommandRoutes = RoutesList;
export type CommandKillsUpdated = Kill[];
export type CommandSelectSystem = string | undefined;
export type CommandCenterSystem = string | undefined;
export type CommandLinkSignatureToSystem = {
solar_system_source: number;
solar_system_target: number;
signatures: any[];
};
export interface CommandData {
[Commands.init]: CommandInit;
@@ -94,6 +101,7 @@ export interface CommandData {
[Commands.killsUpdated]: CommandKillsUpdated;
[Commands.selectSystem]: CommandSelectSystem;
[Commands.centerSystem]: CommandCenterSystem;
[Commands.linkSignatureToSystem]: CommandLinkSignatureToSystem;
}
export interface MapHandlers {
@@ -129,6 +137,7 @@ export enum OutCommand {
addCharacter = 'add_character',
openUserSettings = 'open_user_settings',
getPassages = 'get_passages',
linkSignatureToSystem = 'link_signature_to_system',
// Only UI commands
openSettings = 'open_settings',

View File

@@ -1,9 +1,12 @@
import { SolarSystemStaticInfoRaw } from '@/hooks/Mapper/types';
export type SystemSignature = {
eve_id: string;
kind: string;
name: string;
description?: string;
group: string;
linked_system?: SolarSystemStaticInfoRaw;
updated_at?: string;
};

View File

@@ -28,6 +28,7 @@
"primeicons": "^7.0.0",
"primereact": "^10.6.5",
"react-error-boundary": "^4.0.13",
"react-event-hook": "^3.1.2",
"react-flow-renderer": "^10.3.17",
"react-grid-layout": "^1.3.4",
"react-usestateref": "^1.0.9",

View File

@@ -3199,6 +3199,11 @@ react-error-boundary@^4.0.13:
dependencies:
"@babel/runtime" "^7.12.5"
react-event-hook@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/react-event-hook/-/react-event-hook-3.1.2.tgz#445e8f3b751f6abe4ef199f31bff47593c4c13d4"
integrity sha512-qQ9LXLdxmWRRZPlnqVjqlw7jovSvDosQEOyQ9cjPHhtDv8JIszjj0td1PuHJHrVW0LS8a1XeJhLe6i7S5u9SbQ==
react-flow-renderer@^10.3.17:
version "10.3.17"
resolved "https://registry.npmjs.org/react-flow-renderer/-/react-flow-renderer-10.3.17.tgz"

View File

@@ -14,6 +14,7 @@ defmodule WandererApp.Api.MapSystemSignature do
define(:all_active, action: :all_active)
define(:create, action: :create)
define(:update, action: :update)
define(:update_linked_system, action: :update_linked_system)
define(:by_id,
get_by: [:id],
@@ -66,13 +67,18 @@ defmodule WandererApp.Api.MapSystemSignature do
:name,
:description,
:kind,
:group
:group,
:linked_system_id
]
primary? true
require_atomic? false
end
update :update_linked_system do
accept [:linked_system_id]
end
read :by_system_id do
argument(:system_id, :string, allow_nil?: false)
@@ -99,6 +105,10 @@ defmodule WandererApp.Api.MapSystemSignature do
allow_nil? true
end
attribute :linked_system_id, :integer do
allow_nil? true
end
attribute :kind, :string
attribute :group, :string

View File

@@ -1627,9 +1627,17 @@ defmodule WandererApp.Map.Server.Impl do
solar_system_target: location.solar_system_id
})
broadcast!(map_id, :add_connection, connection)
WandererApp.Map.add_connection(map_id, connection)
broadcast!(map_id, :add_connection, connection)
broadcast!(map_id, :maybe_link_signature, %{
character_id: character_id,
solar_system_source: old_location.solar_system_id,
solar_system_target: location.solar_system_id,
})
:ok
{:error, error} ->
@logger.debug(fn -> "Failed to add connection: #{inspect(error, pretty: true)}" end)
:ok

View File

@@ -1,7 +1,7 @@
defmodule WandererApp.MapUserSettingsRepo do
use WandererApp, :repository
@default_form_data %{"select_on_spash" => "false"}
@default_form_data %{"select_on_spash" => "false", "link_signature_on_splash" => "false"}
def get(map_id, user_id) do
map_id

View File

@@ -1,3 +1,3 @@
<main class="bg-gradient-to-r from-stone-950 to-stone-900">
<main class="bg-stone-950">
<%= @inner_content %>
</main>

View File

@@ -1,5 +1,5 @@
<main
class="main flex-col !min-h-screen justify-between flex z-0 focus:outline-none transition-all duration-500 opacity-0 phx-page-loading:opacity-0 bg-gradient-to-r from-stone-950 to-stone-900 ccp-font"
class="main flex-col !min-h-screen justify-between flex z-0 focus:outline-none transition-all duration-500 opacity-0 phx-page-loading:opacity-0 bg-stone-950 ccp-font"
phx-mounted={JS.remove_class("opacity-0")}
>
<navbar class="navbar bg-base-100 !sticky top-0 z-50 bg-opacity-0 ">

View File

@@ -5,7 +5,7 @@
</.connection_status>
<main
class="main flex-1 relative z-0 overflow-hidden focus:outline-none transition-all duration-500 opacity-0 phx-page-loading:opacity-0 bg-gradient-to-r from-stone-950 to-stone-900 maps_bg ccp-font"
class="main flex-1 relative z-0 overflow-hidden focus:outline-none transition-all duration-500 opacity-0 phx-page-loading:opacity-0 bg-stone-950 maps_bg ccp-font"
phx-mounted={JS.remove_class("opacity-0")}
>
<%= @inner_content %>

View File

@@ -1,4 +1,4 @@
<div class="flex flex-col w-0 flex-1 overflow-hidden bg-gradient-to-r from-stone-950 to-stone-900">
<div class="flex flex-col w-0 flex-1 overflow-hidden bg-stone-950">
<.connection_status>
Re-establishing connection...
</.connection_status>

View File

@@ -211,6 +211,67 @@ defmodule WandererAppWeb.MapLive do
{:noreply, socket}
end
@impl true
def handle_info(
%{
event: :maybe_link_signature,
payload: %{
character_id: character_id,
solar_system_source: solar_system_source,
solar_system_target: solar_system_target,
}
},
%{assigns: %{current_user: current_user, map_id: map_id, map_user_settings: map_user_settings}} = socket
) do
is_user_character? =
current_user.characters |> Enum.map(& &1.id) |> Enum.member?(character_id)
link_signature_on_splash? =
map_user_settings
|> WandererApp.MapUserSettingsRepo.to_form_data!()
|> Map.get("link_signature_on_splash", "false")
|> String.to_existing_atom()
{:ok, signatures} =
WandererApp.Api.MapSystem.read_by_map_and_solar_system(%{
map_id: map_id,
solar_system_id: solar_system_source
})
|> case do
{:ok, system} ->
{:ok, get_system_signatures(system.id)}
_ ->
{:ok, []}
end
# signatures
# :
# (4) [{…}, {…}, {…}, {…}]
# solar_system_source
# :
# 31000526
# solar_system_target
# :
# 31001819
#
socket =
(is_user_character? && link_signature_on_splash? && not(signatures |> Enum.empty?()))
|> case do
true ->
socket
|> push_map_event("link_signature_to_system", %{
solar_system_source: solar_system_source,
solar_system_target: solar_system_target,
signatures: signatures
})
false ->
socket
end
{:noreply, socket}
end
@impl true
def handle_info(%{event: :update_map, payload: map_diff}, socket) do
{:noreply,
@@ -1048,7 +1109,7 @@ defmodule WandererAppWeb.MapLive do
s |> WandererApp.Api.MapSystemSignature.create!()
end)
{:reply, %{signatures: _get_system_signatures(system.id)}, socket}
{:reply, %{signatures: get_system_signatures(system.id)}, socket}
_ ->
{:reply, %{signatures: []},
@@ -1079,7 +1140,7 @@ defmodule WandererAppWeb.MapLive do
solar_system_id: solar_system_id |> String.to_integer()
}) do
{:ok, system} ->
{:reply, %{signatures: _get_system_signatures(system.id)}, socket}
{:reply, %{signatures: get_system_signatures(system.id)}, socket}
_ ->
{:reply, %{signatures: []}, socket}
@@ -1530,7 +1591,7 @@ defmodule WandererAppWeb.MapLive do
user_settings_form,
%{assigns: %{map_id: map_id, current_user: current_user}} = socket
) do
settings = user_settings_form |> Map.take(["select_on_spash"]) |> Jason.encode!()
settings = user_settings_form |> Map.take(["select_on_spash", "link_signature_on_splash"]) |> Jason.encode!()
{:ok, user_settings} =
WandererApp.MapUserSettingsRepo.create_or_update(map_id, current_user.id, settings)
@@ -1540,7 +1601,56 @@ defmodule WandererAppWeb.MapLive do
end
@impl true
def handle_event("noop", _, socket), do: {:noreply, socket}
def handle_event(
"link_signature_to_system",
%{
"signature_eve_id" => signature_eve_id,
"solar_system_source" => solar_system_source,
"solar_system_target" => solar_system_target
},
socket
) do
socket
|> _check_user_permissions(:update_system)
|> case do
true ->
case WandererApp.Api.MapSystem.read_by_map_and_solar_system(%{
map_id: socket.assigns.map_id,
solar_system_id: solar_system_source
}) do
{:ok, system} ->
first_character_eve_id =
Map.get(socket.assigns, :user_characters, []) |> List.first()
case not is_nil(first_character_eve_id) do
true ->
WandererApp.Api.MapSystemSignature.by_system_id!(system.id)
|> Enum.filter(fn s -> s.eve_id == signature_eve_id end)
|> Enum.each(fn s ->
s
|> WandererApp.Api.MapSystemSignature.update_linked_system(%{linked_system_id: solar_system_target})
end)
{:noreply, socket}
_ ->
{:noreply,
socket
|> put_flash(
:error,
"You should enable tracking for at least one character to work with signatures."
)}
end
_ ->
{:noreply, socket}
end
_ ->
{:noreply, socket}
end
end
@impl true
def handle_event("show_activity", _, socket) do
@@ -1585,6 +1695,9 @@ defmodule WandererAppWeb.MapLive do
})}
end
@impl true
def handle_event("noop", _, socket), do: {:noreply, socket}
@impl true
def handle_event(event, body, socket) do
Logger.warning(fn -> "unhandled event: #{event} #{inspect(body)}" end)
@@ -1816,11 +1929,11 @@ defmodule WandererAppWeb.MapLive do
end
end
defp _get_system_signatures(system_id),
defp get_system_signatures(system_id),
do:
system_id
|> WandererApp.Api.MapSystemSignature.by_system_id!()
|> Enum.map(fn %{updated_at: updated_at} = s ->
|> Enum.map(fn %{updated_at: updated_at, linked_system_id: linked_system_id} = s ->
s
|> Map.take([
:system_id,
@@ -1832,6 +1945,7 @@ defmodule WandererAppWeb.MapLive do
:group,
:updated_at
])
|> Map.put(:linked_system, get_system_static_info(linked_system_id))
|> Map.put(:updated_at, updated_at |> Calendar.strftime("%Y/%m/%d %H:%M:%S"))
end)
@@ -1897,14 +2011,7 @@ defmodule WandererAppWeb.MapLive do
} = _system,
_include_static_data? \\ true
) do
system_static_info =
case WandererApp.CachedInfo.get_system_static_info(solar_system_id) do
{:ok, system_static_info} ->
map_ui_system_static_info(system_static_info)
_ ->
%{}
end
system_static_info = get_system_static_info(solar_system_id)
%{
id: "#{solar_system_id}",
@@ -1920,6 +2027,18 @@ defmodule WandererAppWeb.MapLive do
}
end
defp get_system_static_info(nil), do: nil
defp get_system_static_info(solar_system_id) do
case WandererApp.CachedInfo.get_system_static_info(solar_system_id) do
{:ok, system_static_info} ->
map_ui_system_static_info(system_static_info)
_ ->
%{}
end
end
defp map_ui_system_static_info(nil), do: %{}
defp map_ui_system_static_info(system_static_info),

View File

@@ -164,5 +164,10 @@
phx-change="update_user_settings"
>
<.input type="checkbox" field={f[:select_on_spash]} label="Auto select splashed systems" />
<.input
type="checkbox"
field={f[:link_signature_on_splash]}
label="Link splashed systems to signatures"
/>
</.form>
</.modal>

View File

@@ -2,7 +2,7 @@ defmodule WandererApp.MixProject do
use Mix.Project
@source_url "https://github.com/wanderer-industries/wanderer"
@version "1.5.0"
@version "1.6.0"
def project do
[

View File

@@ -0,0 +1,21 @@
defmodule WandererApp.Repo.Migrations.AddSignatureLinkedSystem 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(:map_system_signatures_v1) do
add :linked_system_id, :bigint
end
end
def down do
alter table(:map_system_signatures_v1) do
remove :linked_system_id
end
end
end

View File

@@ -0,0 +1,167 @@
{
"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": "eve_id",
"type": "text"
},
{
"allow_nil?": false,
"default": "nil",
"generated?": false,
"primary_key?": false,
"references": null,
"size": null,
"source": "character_eve_id",
"type": "text"
},
{
"allow_nil?": true,
"default": "nil",
"generated?": false,
"primary_key?": false,
"references": null,
"size": null,
"source": "name",
"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": "linked_system_id",
"type": "bigint"
},
{
"allow_nil?": true,
"default": "nil",
"generated?": false,
"primary_key?": false,
"references": null,
"size": null,
"source": "kind",
"type": "text"
},
{
"allow_nil?": true,
"default": "nil",
"generated?": false,
"primary_key?": false,
"references": null,
"size": null,
"source": "group",
"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": "map_system_signatures_v1_system_id_fkey",
"on_delete": null,
"on_update": null,
"primary_key?": true,
"schema": "public",
"table": "map_system_v1"
},
"size": null,
"source": "system_id",
"type": "uuid"
}
],
"base_filter": null,
"check_constraints": [],
"custom_indexes": [],
"custom_statements": [],
"has_create_action": true,
"hash": "B437BC9E9F4607EBD235CBB39B814710E223D532CE09B952C9371257159008F4",
"identities": [
{
"all_tenants?": false,
"base_filter": null,
"index_name": "map_system_signatures_v1_uniq_system_eve_id_index",
"keys": [
{
"type": "atom",
"value": "system_id"
},
{
"type": "atom",
"value": "eve_id"
}
],
"name": "uniq_system_eve_id",
"nils_distinct?": true,
"where": null
}
],
"multitenancy": {
"attribute": null,
"global": null,
"strategy": null
},
"repo": "Elixir.WandererApp.Repo",
"schema": null,
"table": "map_system_signatures_v1"
}