mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-12-10 01:35:33 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0de674adde | ||
|
|
1db65965d0 | ||
|
|
bbed17f631 | ||
|
|
0af4a3a731 | ||
|
|
49d503705a | ||
|
|
c55dd7b8d9 | ||
|
|
7ddcab3537 | ||
|
|
040b46c345 | ||
|
|
cd11ab6775 | ||
|
|
a5d776f3b1 | ||
|
|
e02caf341d | ||
|
|
3c04caa67c | ||
|
|
e76b564cbf | ||
|
|
5b2de88c3d | ||
|
|
82080b232f |
50
CHANGELOG.md
50
CHANGELOG.md
@@ -2,6 +2,56 @@
|
||||
|
||||
<!-- changelog -->
|
||||
|
||||
## [v1.19.0](https://github.com/wanderer-industries/wanderer/compare/v1.18.1...v1.19.0) (2024-11-19)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* Signatures: Add user setting to show Inserted time in a separate column
|
||||
|
||||
## [v1.18.1](https://github.com/wanderer-industries/wanderer/compare/v1.18.0...v1.18.1) (2024-11-17)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.18.0](https://github.com/wanderer-industries/wanderer/compare/v1.17.0...v1.18.0) (2024-11-16)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* Map: a lot of design issues
|
||||
|
||||
## [v1.17.0](https://github.com/wanderer-industries/wanderer/compare/v1.16.1...v1.17.0) (2024-11-15)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* Signatures: Add user setting to show Description in a separate column
|
||||
|
||||
## [v1.16.1](https://github.com/wanderer-industries/wanderer/compare/v1.16.0...v1.16.1) (2024-11-15)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Signatures: Fix signature stored filters
|
||||
|
||||
## [v1.16.0](https://github.com/wanderer-industries/wanderer/compare/v1.15.5...v1.16.0) (2024-11-15)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* Signatures: Add additional filters support to signature list, show description icon
|
||||
|
||||
## [v1.15.5](https://github.com/wanderer-industries/wanderer/compare/v1.15.4...v1.15.5) (2024-11-14)
|
||||
|
||||
|
||||
|
||||
@@ -15,11 +15,10 @@ const ErrorFallback = () => {
|
||||
};
|
||||
|
||||
export default function MapRoot({ hooks }) {
|
||||
const mapRef = useRef<MapHandlers>(null);
|
||||
const providerRef = useRef<MapHandlers>(null);
|
||||
const hooksRef = useRef<any>(hooks);
|
||||
|
||||
const mapperHandlerRefs = useRef([mapRef, providerRef]);
|
||||
const mapperHandlerRefs = useRef([providerRef]);
|
||||
|
||||
const { handleCommand, handleMapEvent, handleMapEvents } = useMapperHandlers(mapperHandlerRefs.current, hooksRef);
|
||||
|
||||
@@ -41,7 +40,7 @@ export default function MapRoot({ hooks }) {
|
||||
|
||||
return (
|
||||
<PrimeReactProvider>
|
||||
<MapRootProvider fwdRef={providerRef} outCommand={handleCommand} mapRef={mapRef}>
|
||||
<MapRootProvider fwdRef={providerRef} outCommand={handleCommand}>
|
||||
<ErrorBoundary FallbackComponent={ErrorFallback} onError={logError}>
|
||||
<ReactFlowProvider>
|
||||
<MapRootContent />
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
import { useCallback } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { useAutoAnimate } from '@formkit/auto-animate/react';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { Commands } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { CharacterTypeRaw } from '@/hooks/Mapper/types';
|
||||
import { emitMapEvent } from '@/hooks/Mapper/events';
|
||||
|
||||
const Characters = ({ data }: { data: CharacterTypeRaw[] }) => {
|
||||
const [parent] = useAutoAnimate();
|
||||
const { mapRef } = useMapRootState();
|
||||
|
||||
const handleSelect = useCallback(
|
||||
(character: CharacterTypeRaw) => {
|
||||
mapRef.current?.command(Commands.centerSystem, character?.location?.solar_system_id?.toString());
|
||||
},
|
||||
[mapRef],
|
||||
);
|
||||
const handleSelect = useCallback((character: CharacterTypeRaw) => {
|
||||
emitMapEvent({
|
||||
name: Commands.centerSystem,
|
||||
data: character?.location?.solar_system_id?.toString(),
|
||||
});
|
||||
}, []);
|
||||
|
||||
const items = data.map(character => (
|
||||
<li
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
import { RefObject, useCallback, useRef, useState } from 'react';
|
||||
import * as React from 'react';
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
import { ContextMenu } from 'primereact/contextmenu';
|
||||
import { Commands, MapHandlers, OutCommand, OutCommandHandler } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { Commands, OutCommand, OutCommandHandler } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { WaypointSetContextHandler } from '@/hooks/Mapper/components/contexts/types.ts';
|
||||
import { ctxManager } from '@/hooks/Mapper/utils/contextManager.ts';
|
||||
import * as React from 'react';
|
||||
import { SolarSystemStaticInfoRaw } from '@/hooks/Mapper/types';
|
||||
import { emitMapEvent } from '@/hooks/Mapper/events';
|
||||
|
||||
interface UseContextMenuSystemHandlersProps {
|
||||
hubs: string[];
|
||||
outCommand: OutCommandHandler;
|
||||
mapRef: RefObject<MapHandlers>;
|
||||
}
|
||||
|
||||
export const useContextMenuSystemInfoHandlers = ({ hubs, outCommand, mapRef }: UseContextMenuSystemHandlersProps) => {
|
||||
export const useContextMenuSystemInfoHandlers = ({ hubs, outCommand }: UseContextMenuSystemHandlersProps) => {
|
||||
const contextMenuRef = useRef<ContextMenu | null>(null);
|
||||
|
||||
const [system, setSystem] = useState<string>();
|
||||
const routeRef = useRef<(SolarSystemStaticInfoRaw | undefined)[]>([]);
|
||||
|
||||
const ref = useRef({ hubs, system, outCommand, mapRef });
|
||||
ref.current = { hubs, system, outCommand, mapRef };
|
||||
const ref = useRef({ hubs, system, outCommand });
|
||||
ref.current = { hubs, system, outCommand };
|
||||
|
||||
const open = useCallback(
|
||||
(ev: React.SyntheticEvent, systemId: string, route: (SolarSystemStaticInfoRaw | undefined)[]) => {
|
||||
@@ -48,7 +48,7 @@ export const useContextMenuSystemInfoHandlers = ({ hubs, outCommand, mapRef }: U
|
||||
}, []);
|
||||
|
||||
const onAddSystem = useCallback(() => {
|
||||
const { system: solarSystemId, outCommand, mapRef } = ref.current;
|
||||
const { system: solarSystemId, outCommand } = ref.current;
|
||||
if (!solarSystemId) {
|
||||
return;
|
||||
}
|
||||
@@ -60,7 +60,11 @@ export const useContextMenuSystemInfoHandlers = ({ hubs, outCommand, mapRef }: U
|
||||
},
|
||||
});
|
||||
setTimeout(() => {
|
||||
mapRef.current?.command(Commands.centerSystem, solarSystemId);
|
||||
emitMapEvent({
|
||||
name: Commands.centerSystem,
|
||||
data: solarSystemId,
|
||||
});
|
||||
|
||||
setSystem(undefined);
|
||||
}, 200);
|
||||
}, []);
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { ForwardedRef, forwardRef, MouseEvent, useCallback, useEffect, useRef } from 'react';
|
||||
import { ForwardedRef, forwardRef, MouseEvent, useCallback, useEffect } from 'react';
|
||||
import ReactFlow, {
|
||||
Background,
|
||||
ConnectionMode,
|
||||
Edge,
|
||||
MiniMap,
|
||||
Node,
|
||||
NodeChange,
|
||||
NodeDragHandler,
|
||||
OnConnect,
|
||||
OnMoveEnd,
|
||||
@@ -13,7 +14,6 @@ import ReactFlow, {
|
||||
SelectionMode,
|
||||
useEdgesState,
|
||||
useNodesState,
|
||||
NodeChange,
|
||||
useReactFlow,
|
||||
} from 'reactflow';
|
||||
import 'reactflow/dist/style.css';
|
||||
@@ -21,7 +21,6 @@ import classes from './Map.module.scss';
|
||||
import './styles/neon-theme.scss';
|
||||
import './styles/eve-common.scss';
|
||||
import { MapProvider, useMapState } from './MapProvider';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { useMapHandlers, useUpdateNodes } from './hooks';
|
||||
import { MapHandlers, OutCommand, OutCommandHandler } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import {
|
||||
@@ -37,7 +36,6 @@ import { SESSION_KEY } from '@/hooks/Mapper/constants.ts';
|
||||
import { SolarSystemConnection, SolarSystemRawType } from '@/hooks/Mapper/types';
|
||||
import { ctxManager } from '@/hooks/Mapper/utils/contextManager.ts';
|
||||
import { NodeSelectionMouseHandler } from '@/hooks/Mapper/components/contexts/types.ts';
|
||||
import { useDeleteSystems } from '@/hooks/Mapper/components/contexts/hooks';
|
||||
|
||||
const DEFAULT_VIEW_PORT = { zoom: 1, x: 0, y: 0 };
|
||||
|
||||
@@ -93,12 +91,14 @@ interface MapCompProps {
|
||||
refn: ForwardedRef<MapHandlers>;
|
||||
onCommand: OutCommandHandler;
|
||||
onSelectionChange: OnMapSelectionChange;
|
||||
onManualDelete(systems: string[]): void;
|
||||
onConnectionInfoClick?(e: SolarSystemConnection): void;
|
||||
onSelectionContextMenu?: NodeSelectionMouseHandler;
|
||||
minimapClasses?: string;
|
||||
isShowMinimap?: boolean;
|
||||
onSystemContextMenu: (event: MouseEvent<Element>, systemId: string) => void;
|
||||
showKSpaceBG?: boolean;
|
||||
isThickConnections?: boolean;
|
||||
}
|
||||
|
||||
const MapComp = ({
|
||||
@@ -109,8 +109,10 @@ const MapComp = ({
|
||||
onSystemContextMenu,
|
||||
onConnectionInfoClick,
|
||||
onSelectionContextMenu,
|
||||
onManualDelete,
|
||||
isShowMinimap,
|
||||
showKSpaceBG,
|
||||
isThickConnections,
|
||||
}: MapCompProps) => {
|
||||
const { getNode } = useReactFlow();
|
||||
const [nodes, , onNodesChange] = useNodesState<SolarSystemRawType>(initialNodes);
|
||||
@@ -121,14 +123,6 @@ const MapComp = ({
|
||||
const { handleRootContext, ...rootCtxProps } = useContextMenuRootHandlers();
|
||||
const { handleConnectionContext, ...connectionCtxProps } = useContextMenuConnectionHandlers();
|
||||
const { update } = useMapState();
|
||||
const {
|
||||
data: { systems },
|
||||
} = useMapRootState();
|
||||
|
||||
const { deleteSystems } = useDeleteSystems();
|
||||
|
||||
const systemsRef = useRef({ systems });
|
||||
systemsRef.current = { systems };
|
||||
|
||||
const onConnect: OnConnect = useCallback(
|
||||
params => {
|
||||
@@ -186,35 +180,41 @@ const MapComp = ({
|
||||
const handleNodesChange = useCallback(
|
||||
(changes: NodeChange[]) => {
|
||||
const systemsIdsToRemove: string[] = [];
|
||||
|
||||
const nextChanges = changes.reduce((acc, change) => {
|
||||
if (change.type === 'remove') {
|
||||
const node = getNode(change.id);
|
||||
const { systems = [] } = systemsRef.current;
|
||||
if (node?.data?.id && !systems.map(s => s.id).includes(node?.data?.id)) {
|
||||
return [...acc, change];
|
||||
} else if (!node?.data?.locked) {
|
||||
systemsIdsToRemove.push(node?.data?.id);
|
||||
}
|
||||
if (change.type !== 'remove') {
|
||||
return [...acc, change];
|
||||
}
|
||||
|
||||
const node = getNode(change.id);
|
||||
if (!node) {
|
||||
return [...acc, change];
|
||||
}
|
||||
|
||||
if (node.data.locked) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
systemsIdsToRemove.push(node.data.id);
|
||||
return [...acc, change];
|
||||
}, [] as NodeChange[]);
|
||||
|
||||
if (systemsIdsToRemove.length) {
|
||||
deleteSystems(systemsIdsToRemove);
|
||||
if (systemsIdsToRemove.length > 0) {
|
||||
onManualDelete(systemsIdsToRemove);
|
||||
}
|
||||
|
||||
onNodesChange(nextChanges);
|
||||
},
|
||||
[deleteSystems, getNode, onNodesChange],
|
||||
[getNode, onManualDelete, onNodesChange],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
update(x => ({
|
||||
...x,
|
||||
showKSpaceBG: showKSpaceBG,
|
||||
isThickConnections: isThickConnections,
|
||||
}));
|
||||
}, [showKSpaceBG, update]);
|
||||
}, [showKSpaceBG, isThickConnections, update]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -238,6 +238,7 @@ const MapComp = ({
|
||||
onConnectStart={() => update({ isConnecting: true })}
|
||||
onConnectEnd={() => update({ isConnecting: false })}
|
||||
onNodeMouseEnter={(_, node) => update({ hoverNodeId: node.id })}
|
||||
// onKeyUp=
|
||||
onNodeMouseLeave={() => update({ hoverNodeId: null })}
|
||||
onEdgeClick={(_, t) => {
|
||||
onConnectionInfoClick?.(t.data);
|
||||
|
||||
@@ -8,6 +8,7 @@ export type MapData = MapUnionTypes & {
|
||||
hoverNodeId: string | null;
|
||||
visibleNodes: Set<string>;
|
||||
showKSpaceBG: boolean;
|
||||
isThickConnections: boolean;
|
||||
};
|
||||
|
||||
interface MapProviderProps {
|
||||
@@ -17,6 +18,7 @@ interface MapProviderProps {
|
||||
|
||||
const INITIAL_DATA: MapData = {
|
||||
wormholesData: {},
|
||||
wormholes: [],
|
||||
effects: {},
|
||||
characters: [],
|
||||
userCharacters: [],
|
||||
@@ -29,6 +31,7 @@ const INITIAL_DATA: MapData = {
|
||||
hoverNodeId: null,
|
||||
visibleNodes: new Set(),
|
||||
showKSpaceBG: false,
|
||||
isThickConnections: false,
|
||||
};
|
||||
|
||||
export interface MapContextProps {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
}
|
||||
|
||||
&.Frigate {
|
||||
stroke: #4e62c9;
|
||||
stroke: #d4f0ff;
|
||||
}
|
||||
|
||||
&.Hovered {
|
||||
@@ -37,9 +37,16 @@
|
||||
}
|
||||
|
||||
&.Frigate {
|
||||
stroke: #41acd7;
|
||||
stroke: #d4f0ff;
|
||||
}
|
||||
}
|
||||
|
||||
&.Tick {
|
||||
stroke-width: 3px;
|
||||
|
||||
&.Hovered {
|
||||
stroke-width: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +68,14 @@
|
||||
stroke: #ef7dce;
|
||||
}
|
||||
}
|
||||
|
||||
&.Tick {
|
||||
stroke-width: 5px;
|
||||
|
||||
&.TimeCrit {
|
||||
stroke-width: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ClickPath {
|
||||
@@ -93,5 +108,14 @@
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
z-index: 1001;
|
||||
|
||||
&.Tick {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
|
||||
&.Right {
|
||||
margin-left: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,33 +7,54 @@ import clsx from 'clsx';
|
||||
import { MassState, ShipSizeStatus, SolarSystemConnection, TimeStatus } from '@/hooks/Mapper/types';
|
||||
import { PrimeIcons } from 'primereact/api';
|
||||
import { WdTooltipWrapper } from '@/hooks/Mapper/components/ui-kit/WdTooltipWrapper';
|
||||
import { useMapState } from '@/hooks/Mapper/components/map/MapProvider.tsx';
|
||||
|
||||
const MAP_TRANSLATES: Record<string, string> = {
|
||||
[Position.Top]: 'translate(-50%, 0%)',
|
||||
[Position.Top]: 'translate(-48%, 0%)',
|
||||
[Position.Bottom]: 'translate(-50%, -100%)',
|
||||
[Position.Left]: 'translate(0%, -50%)',
|
||||
[Position.Right]: 'translate(-100%, -50%)',
|
||||
};
|
||||
|
||||
const MAP_OFFSETS_TICK: Record<string, { x: number; y: number }> = {
|
||||
[Position.Top]: { x: 0, y: 3 },
|
||||
[Position.Bottom]: { x: 0, y: -3 },
|
||||
[Position.Left]: { x: 3, y: 0 },
|
||||
[Position.Right]: { x: -3, y: 0 },
|
||||
};
|
||||
|
||||
const MAP_OFFSETS: Record<string, { x: number; y: number }> = {
|
||||
[Position.Top]: { x: 0, y: 0 },
|
||||
[Position.Bottom]: { x: 0, y: 0 },
|
||||
[Position.Left]: { x: 0, y: 0 },
|
||||
[Position.Right]: { x: 0, y: 0 },
|
||||
};
|
||||
|
||||
export const SolarSystemEdge = ({ id, source, target, markerEnd, style, data }: EdgeProps<SolarSystemConnection>) => {
|
||||
const sourceNode = useStore(useCallback(store => store.nodeInternals.get(source), [source]));
|
||||
const targetNode = useStore(useCallback(store => store.nodeInternals.get(target), [target]));
|
||||
|
||||
const {
|
||||
data: { isThickConnections },
|
||||
} = useMapState();
|
||||
|
||||
const [hovered, setHovered] = useState(false);
|
||||
|
||||
const [path, labelX, labelY, sx, sy, tx, ty, sourcePos, targetPos] = useMemo(() => {
|
||||
const { sx, sy, tx, ty, sourcePos, targetPos } = getEdgeParams(sourceNode, targetNode);
|
||||
|
||||
const offset = isThickConnections ? MAP_OFFSETS_TICK[targetPos] : MAP_OFFSETS[targetPos];
|
||||
|
||||
const [edgePath, labelX, labelY] = getBezierPath({
|
||||
sourceX: sx,
|
||||
sourceY: sy,
|
||||
sourceX: sx - offset.x,
|
||||
sourceY: sy - offset.y,
|
||||
sourcePosition: sourcePos,
|
||||
targetPosition: targetPos,
|
||||
targetX: tx,
|
||||
targetY: ty,
|
||||
targetX: tx + offset.x,
|
||||
targetY: ty + offset.y,
|
||||
});
|
||||
return [edgePath, labelX, labelY, sx, sy, tx, ty, sourcePos, targetPos];
|
||||
}, [sourceNode, targetNode]);
|
||||
}, [isThickConnections, sourceNode, targetNode]);
|
||||
|
||||
if (!sourceNode || !targetNode || !data) {
|
||||
return null;
|
||||
@@ -44,6 +65,7 @@ export const SolarSystemEdge = ({ id, source, target, markerEnd, style, data }:
|
||||
<path
|
||||
id={`back_${id}`}
|
||||
className={clsx(classes.EdgePathBack, {
|
||||
[classes.Tick]: isThickConnections,
|
||||
[classes.TimeCrit]: data.time_status === TimeStatus.eol,
|
||||
[classes.Hovered]: hovered,
|
||||
})}
|
||||
@@ -54,6 +76,7 @@ export const SolarSystemEdge = ({ id, source, target, markerEnd, style, data }:
|
||||
<path
|
||||
id={`front_${id}`}
|
||||
className={clsx(classes.EdgePathFront, {
|
||||
[classes.Tick]: isThickConnections,
|
||||
[classes.Hovered]: hovered,
|
||||
[classes.MassVerge]: data.mass_status === MassState.verge,
|
||||
[classes.MassHalf]: data.mass_status === MassState.half,
|
||||
@@ -75,11 +98,19 @@ export const SolarSystemEdge = ({ id, source, target, markerEnd, style, data }:
|
||||
|
||||
<EdgeLabelRenderer>
|
||||
<div
|
||||
className={clsx(classes.Handle, 'react-flow__handle absolute nodrag pointer-events-none')}
|
||||
className={clsx(
|
||||
classes.Handle,
|
||||
{ [classes.Tick]: isThickConnections, [classes.Right]: Position.Right === sourcePos },
|
||||
'react-flow__handle absolute nodrag pointer-events-none',
|
||||
)}
|
||||
style={{ transform: `${MAP_TRANSLATES[sourcePos]} translate(${sx}px,${sy}px)` }}
|
||||
/>
|
||||
<div
|
||||
className={clsx(classes.Handle, 'react-flow__handle absolute nodrag pointer-events-none')}
|
||||
className={clsx(
|
||||
classes.Handle,
|
||||
{ [classes.Tick]: isThickConnections },
|
||||
'react-flow__handle absolute nodrag pointer-events-none',
|
||||
)}
|
||||
style={{ transform: `${MAP_TRANSLATES[targetPos]} translate(${tx}px,${ty}px)` }}
|
||||
/>
|
||||
|
||||
|
||||
@@ -212,6 +212,14 @@ $tooltip-bg: #202020; // Темный фон для подсказок
|
||||
color: #ffb01d;
|
||||
}
|
||||
|
||||
/* Firefox kostyl */
|
||||
@-moz-document url-prefix() {
|
||||
.classSystemName {
|
||||
font-family: inherit !important;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.classSystemName {
|
||||
//font-weight: bold;
|
||||
}
|
||||
@@ -262,6 +270,13 @@ $tooltip-bg: #202020; // Темный фон для подсказок
|
||||
& > * {
|
||||
line-height: 10px;
|
||||
}
|
||||
|
||||
/* Firefox kostyl */
|
||||
@-moz-document url-prefix() {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.Handlers {
|
||||
@@ -299,4 +314,25 @@ $tooltip-bg: #202020; // Темный фон для подсказок
|
||||
&.HandleLeft {
|
||||
left: -2px;
|
||||
}
|
||||
|
||||
&.Tick {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
|
||||
&.HandleTop {
|
||||
top: -3px;
|
||||
}
|
||||
|
||||
&.HandleRight {
|
||||
right: -3px;
|
||||
}
|
||||
|
||||
&.HandleBottom {
|
||||
bottom: -3px;
|
||||
}
|
||||
|
||||
&.HandleLeft {
|
||||
left: -3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ export const SolarSystemNode = memo(({ data, selected }: WrapNodeProps<MapSolarS
|
||||
hoverNodeId,
|
||||
visibleNodes,
|
||||
showKSpaceBG,
|
||||
isThickConnections,
|
||||
},
|
||||
outCommand,
|
||||
} = useMapState();
|
||||
@@ -239,28 +240,40 @@ export const SolarSystemNode = memo(({ data, selected }: WrapNodeProps<MapSolarS
|
||||
<div onMouseDownCapture={dbClick} className={classes.Handlers}>
|
||||
<Handle
|
||||
type="source"
|
||||
className={clsx(classes.Handle, classes.HandleTop, { [classes.selected]: selected })}
|
||||
className={clsx(classes.Handle, classes.HandleTop, {
|
||||
[classes.selected]: selected,
|
||||
[classes.Tick]: isThickConnections,
|
||||
})}
|
||||
style={{ visibility: showHandlers ? 'visible' : 'hidden' }}
|
||||
position={Position.Top}
|
||||
id="a"
|
||||
/>
|
||||
<Handle
|
||||
type="source"
|
||||
className={clsx(classes.Handle, classes.HandleRight, { [classes.selected]: selected })}
|
||||
className={clsx(classes.Handle, classes.HandleRight, {
|
||||
[classes.selected]: selected,
|
||||
[classes.Tick]: isThickConnections,
|
||||
})}
|
||||
style={{ visibility: showHandlers ? 'visible' : 'hidden' }}
|
||||
position={Position.Right}
|
||||
id="b"
|
||||
/>
|
||||
<Handle
|
||||
type="source"
|
||||
className={clsx(classes.Handle, classes.HandleBottom, { [classes.selected]: selected })}
|
||||
className={clsx(classes.Handle, classes.HandleBottom, {
|
||||
[classes.selected]: selected,
|
||||
[classes.Tick]: isThickConnections,
|
||||
})}
|
||||
style={{ visibility: showHandlers ? 'visible' : 'hidden' }}
|
||||
position={Position.Bottom}
|
||||
id="c"
|
||||
/>
|
||||
<Handle
|
||||
type="source"
|
||||
className={clsx(classes.Handle, classes.HandleLeft, { [classes.selected]: selected })}
|
||||
className={clsx(classes.Handle, classes.HandleLeft, {
|
||||
[classes.selected]: selected,
|
||||
[classes.Tick]: isThickConnections,
|
||||
})}
|
||||
style={{ visibility: showHandlers ? 'visible' : 'hidden' }}
|
||||
position={Position.Left}
|
||||
id="d"
|
||||
|
||||
@@ -5,24 +5,21 @@ import { OnMapSelectionChange } from '@/hooks/Mapper/components/map/map.types.ts
|
||||
|
||||
export const useMapRemoveSystems = (onSelectionChange: OnMapSelectionChange) => {
|
||||
const rf = useReactFlow();
|
||||
const ref = useRef({ onSelectionChange });
|
||||
ref.current = { onSelectionChange };
|
||||
const ref = useRef({ onSelectionChange, rf });
|
||||
ref.current = { onSelectionChange, rf };
|
||||
|
||||
return useCallback(
|
||||
(systems: CommandRemoveSystems) => {
|
||||
rf.deleteElements({ nodes: systems.map(x => ({ id: `${x}` })) });
|
||||
return useCallback((systems: CommandRemoveSystems) => {
|
||||
ref.current.rf.deleteElements({ nodes: systems.map(x => ({ id: `${x}` })) });
|
||||
|
||||
const newSelection = rf
|
||||
.getNodes()
|
||||
.filter(x => !systems.includes(parseInt(x.id)))
|
||||
.filter(x => x.selected)
|
||||
.map(x => x.id);
|
||||
const newSelection = ref.current.rf
|
||||
.getNodes()
|
||||
.filter(x => !systems.includes(parseInt(x.id)))
|
||||
.filter(x => x.selected)
|
||||
.map(x => x.id);
|
||||
|
||||
ref.current.onSelectionChange({
|
||||
systems: newSelection,
|
||||
connections: [],
|
||||
});
|
||||
},
|
||||
[rf],
|
||||
);
|
||||
ref.current.onSelectionChange({
|
||||
systems: newSelection,
|
||||
connections: [],
|
||||
});
|
||||
}, []);
|
||||
};
|
||||
|
||||
@@ -19,8 +19,6 @@ import {
|
||||
MapHandlers,
|
||||
} from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
|
||||
import { useMapEventListener } from '@/hooks/Mapper/events';
|
||||
|
||||
import {
|
||||
useCommandsCharacters,
|
||||
useCommandsConnections,
|
||||
@@ -60,13 +58,16 @@ export const useMapHandlers = (ref: ForwardedRef<MapHandlers>, onSelectionChange
|
||||
mapInit(data as CommandInit);
|
||||
break;
|
||||
case Commands.addSystems:
|
||||
setTimeout(() => mapAddSystems(data as CommandAddSystems), 100);
|
||||
break;
|
||||
case Commands.updateSystems:
|
||||
mapUpdateSystems(data as CommandUpdateSystems);
|
||||
break;
|
||||
case Commands.removeSystems:
|
||||
setTimeout(() => removeSystems(data as CommandRemoveSystems), 100);
|
||||
break;
|
||||
case Commands.addConnections:
|
||||
setTimeout(() => addConnections(data as CommandAddConnections), 100);
|
||||
break;
|
||||
case Commands.removeConnections:
|
||||
removeConnections(data as CommandRemoveConnections);
|
||||
@@ -131,20 +132,4 @@ export const useMapHandlers = (ref: ForwardedRef<MapHandlers>, onSelectionChange
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
useMapEventListener(event => {
|
||||
switch (event.name) {
|
||||
case Commands.addConnections:
|
||||
addConnections(event.data as CommandAddConnections);
|
||||
break;
|
||||
case Commands.addSystems:
|
||||
mapAddSystems(event.data as CommandAddSystems);
|
||||
break;
|
||||
case Commands.removeSystems:
|
||||
removeSystems(event.data as CommandRemoveSystems);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -10,13 +10,17 @@ import {
|
||||
Setting,
|
||||
COSMIC_SIGNATURE,
|
||||
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignatureSettingsDialog';
|
||||
import { SignatureGroup } from '@/hooks/Mapper/types';
|
||||
|
||||
interface SystemLinkSignatureDialogProps {
|
||||
data: CommandLinkSignatureToSystem;
|
||||
setVisible: (visible: boolean) => void;
|
||||
}
|
||||
|
||||
const signatureSettings: Setting[] = [{ key: COSMIC_SIGNATURE, name: 'Show Cosmic Signatures', value: true }];
|
||||
const signatureSettings: Setting[] = [
|
||||
{ key: COSMIC_SIGNATURE, name: 'Show Cosmic Signatures', value: true },
|
||||
{ key: SignatureGroup.Wormhole, name: 'Wormhole', value: true },
|
||||
];
|
||||
|
||||
export const SystemLinkSignatureDialog = ({ data, setVisible }: SystemLinkSignatureDialogProps) => {
|
||||
const { outCommand } = useMapRootState();
|
||||
@@ -59,6 +63,7 @@ export const SystemLinkSignatureDialog = ({ data, setVisible }: SystemLinkSignat
|
||||
>
|
||||
<SystemSignaturesContent
|
||||
systemId={`${data.solar_system_source}`}
|
||||
hideLinkedSignatures
|
||||
settings={signatureSettings}
|
||||
onSelect={handleSelect}
|
||||
selectable={true}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { SystemViewStandalone, WdTooltip, WdTooltipHandlers } from '@/hooks/Mapp
|
||||
import { getBackgroundClass, getShapeClass } from '@/hooks/Mapper/components/map/helpers';
|
||||
import { MouseEvent, useCallback, useRef, useState } from 'react';
|
||||
import { Commands } from '@/hooks/Mapper/types';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { emitMapEvent } from '@/hooks/Mapper/events';
|
||||
|
||||
export type RouteSystemProps = {
|
||||
destination: number;
|
||||
@@ -88,11 +88,10 @@ export interface RoutesListProps {
|
||||
|
||||
export const RoutesList = ({ data, onContextMenu }: RoutesListProps) => {
|
||||
const [selected, setSelected] = useState<number | null>(null);
|
||||
const { mapRef } = useMapRootState();
|
||||
|
||||
const handleClick = useCallback(
|
||||
(systemId: number) => mapRef.current?.command(Commands.centerSystem, systemId.toString()),
|
||||
[mapRef],
|
||||
(systemId: number) => emitMapEvent({ name: Commands.centerSystem, data: systemId?.toString() }),
|
||||
[],
|
||||
);
|
||||
|
||||
if (!data.has_connection) {
|
||||
|
||||
@@ -30,7 +30,6 @@ const sortByDist = (a: Route, b: Route) => {
|
||||
export const RoutesWidgetContent = () => {
|
||||
const {
|
||||
data: { selectedSystems, hubs = [], systems, routes },
|
||||
mapRef,
|
||||
outCommand,
|
||||
} = useMapRootState();
|
||||
|
||||
@@ -42,7 +41,6 @@ export const RoutesWidgetContent = () => {
|
||||
const { open, ...systemCtxProps } = useContextMenuSystemInfoHandlers({
|
||||
outCommand,
|
||||
hubs,
|
||||
mapRef,
|
||||
});
|
||||
|
||||
const preparedHubs = useMemo(() => {
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
.verticalTabsContainer {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
min-height: 300px;
|
||||
|
||||
:global {
|
||||
.p-tabview {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.p-tabview-panels {
|
||||
padding: 6px 1rem !important;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.p-tabview-nav-container {
|
||||
border-right: none;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.p-tabview-nav {
|
||||
flex-direction: column;
|
||||
width: 150px;
|
||||
min-height: 100%;
|
||||
border: none;
|
||||
|
||||
li {
|
||||
width: 100%;
|
||||
border-right: 4px solid var(--surface-hover);
|
||||
background-color: var(--surface-card);
|
||||
|
||||
transition:
|
||||
background-color 200ms,
|
||||
border-right-color 200ms;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--surface-hover);
|
||||
border-right: 4px solid var(--surface-100);
|
||||
}
|
||||
|
||||
.p-tabview-nav-link {
|
||||
transition: color 200ms;
|
||||
|
||||
justify-content: flex-end;
|
||||
padding: 10px;
|
||||
//background-color: var(--surface-card);
|
||||
background-color: initial;
|
||||
border: none;
|
||||
color: var(--gray-400);
|
||||
|
||||
border-radius: initial;
|
||||
font-weight: 400;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&.p-tabview-selected {
|
||||
background-color: var(--surface-50);
|
||||
border-right: 4px solid var(--primary-color);
|
||||
|
||||
.p-tabview-nav-link {
|
||||
font-weight: 600;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
//background-color: var(--surface-hover);
|
||||
border-right: 4px solid var(--primary-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.p-tabview-panel {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,10 @@ import { Dialog } from 'primereact/dialog';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Checkbox } from 'primereact/checkbox';
|
||||
import { TabPanel, TabView } from 'primereact/tabview';
|
||||
import styles from './SystemSignatureSettingsDialog.module.scss';
|
||||
|
||||
export type Setting = { key: string; name: string; value: boolean };
|
||||
export type Setting = { key: string; name: string; value: boolean; isFilter?: boolean };
|
||||
|
||||
export const COSMIC_SIGNATURE = 'Cosmic Signature';
|
||||
export const COSMIC_ANOMALY = 'Cosmic Anomaly';
|
||||
@@ -24,8 +26,12 @@ export const SystemSignatureSettingsDialog = ({
|
||||
onSave,
|
||||
onCancel,
|
||||
}: SystemSignatureSettingsDialogProps) => {
|
||||
const [activeIndex, setActiveIndex] = useState(0);
|
||||
const [settings, setSettings] = useState<Setting[]>(defaultSettings);
|
||||
|
||||
const filterSettings = settings.filter(setting => setting.isFilter);
|
||||
const userSettings = settings.filter(setting => !setting.isFilter);
|
||||
|
||||
const handleSettingsChange = (key: string) => {
|
||||
setSettings(prevState => prevState.map(item => (item.key === key ? { ...item, value: !item.value } : item)));
|
||||
};
|
||||
@@ -35,23 +41,53 @@ export const SystemSignatureSettingsDialog = ({
|
||||
}, [onSave, settings]);
|
||||
|
||||
return (
|
||||
<Dialog header="Filter signatures" visible draggable={false} style={{ width: '300px' }} onHide={onCancel}>
|
||||
<Dialog header="System Signatures Settings" visible={true} onHide={onCancel} className="w-full max-w-lg">
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex flex-col gap-2">
|
||||
{settings.map(setting => {
|
||||
return (
|
||||
<div key={setting.key} className="flex items-center">
|
||||
<Checkbox
|
||||
inputId={setting.key}
|
||||
checked={setting.value}
|
||||
onChange={() => handleSettingsChange(setting.key)}
|
||||
/>
|
||||
<label htmlFor={setting.key} className="ml-2">
|
||||
{setting.name}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<div className={styles.verticalTabsContainer}>
|
||||
<TabView
|
||||
activeIndex={activeIndex}
|
||||
onTabChange={e => setActiveIndex(e.index)}
|
||||
className={styles.verticalTabView}
|
||||
>
|
||||
<TabPanel header="Filters" headerClassName={styles.verticalTabHeader}>
|
||||
<div className="w-full h-full flex flex-col gap-1">
|
||||
{filterSettings.map(setting => {
|
||||
return (
|
||||
<div key={setting.key} className="flex items-center">
|
||||
<Checkbox
|
||||
inputId={setting.key}
|
||||
checked={setting.value}
|
||||
onChange={() => handleSettingsChange(setting.key)}
|
||||
/>
|
||||
<label htmlFor={setting.key} className="ml-2">
|
||||
{setting.name}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</TabPanel>
|
||||
<TabPanel header="User Interface" headerClassName={styles.verticalTabHeader}>
|
||||
<div className="w-full h-full flex flex-col gap-1">
|
||||
{userSettings.map(setting => {
|
||||
return (
|
||||
<div key={setting.key} className="flex items-center">
|
||||
<Checkbox
|
||||
inputId={setting.key}
|
||||
checked={setting.value}
|
||||
onChange={() => handleSettingsChange(setting.key)}
|
||||
/>
|
||||
<label htmlFor={setting.key} className="ml-2">
|
||||
{setting.name}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</TabPanel>
|
||||
</TabView>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 justify-end">
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
SHIP,
|
||||
DRONE,
|
||||
} from './SystemSignatureSettingsDialog';
|
||||
import { SignatureGroup } from '@/hooks/Mapper/types';
|
||||
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
@@ -19,17 +20,27 @@ import { PrimeIcons } from 'primereact/api';
|
||||
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
|
||||
const settings: Setting[] = [
|
||||
{ key: COSMIC_ANOMALY, name: 'Show Anomalies', value: true },
|
||||
{ key: COSMIC_SIGNATURE, name: 'Show Cosmic Signatures', value: true },
|
||||
{ key: DEPLOYABLE, name: 'Show Deployables', value: true },
|
||||
{ key: STRUCTURE, name: 'Show Structures', value: true },
|
||||
{ key: STARBASE, name: 'Show Starbase', value: true },
|
||||
{ key: SHIP, name: 'Show Ships', value: true },
|
||||
{ key: DRONE, name: 'Show Drones And Charges', value: true },
|
||||
];
|
||||
const SIGNATURE_SETTINGS_KEY = 'wanderer_system_signature_settings_v4_1';
|
||||
export const SHOW_DESCRIPTION_COLUMN_SETTING = 'show_description_column_setting';
|
||||
export const SHOW_INSERTED_COLUMN_SETTING = 'show_inserted_column_setting';
|
||||
|
||||
const SIGNATURE_SETTINGS_KEY = 'wanderer_system_signature_settings';
|
||||
const settings: Setting[] = [
|
||||
{ key: SHOW_INSERTED_COLUMN_SETTING, name: 'Show Inserted Column', value: false, isFilter: false },
|
||||
{ key: SHOW_DESCRIPTION_COLUMN_SETTING, name: 'Show Description Column', value: false, isFilter: false },
|
||||
{ key: COSMIC_ANOMALY, name: 'Show Anomalies', value: true, isFilter: true },
|
||||
{ key: COSMIC_SIGNATURE, name: 'Show Cosmic Signatures', value: true, isFilter: true },
|
||||
{ key: DEPLOYABLE, name: 'Show Deployables', value: true, isFilter: true },
|
||||
{ key: STRUCTURE, name: 'Show Structures', value: true, isFilter: true },
|
||||
{ key: STARBASE, name: 'Show Starbase', value: true, isFilter: true },
|
||||
{ key: SHIP, name: 'Show Ships', value: true, isFilter: true },
|
||||
{ key: DRONE, name: 'Show Drones And Charges', value: true, isFilter: true },
|
||||
{ key: SignatureGroup.Wormhole, name: 'Show Wormholes', value: true, isFilter: true },
|
||||
{ key: SignatureGroup.RelicSite, name: 'Show Relic Sites', value: true, isFilter: true },
|
||||
{ key: SignatureGroup.DataSite, name: 'Show Data Sites', value: true, isFilter: true },
|
||||
{ key: SignatureGroup.OreSite, name: 'Show Ore Sites', value: true, isFilter: true },
|
||||
{ key: SignatureGroup.GasSite, name: 'Show Gas Sites', value: true, isFilter: true },
|
||||
{ key: SignatureGroup.CombatSite, name: 'Show Combat Sites', value: true, isFilter: true },
|
||||
];
|
||||
|
||||
const defaultSettings = () => {
|
||||
return [...settings];
|
||||
@@ -91,8 +102,7 @@ export const SystemSignatures = () => {
|
||||
</InfoDrawer>
|
||||
<InfoDrawer title={<b className="text-slate-50">How to delete?</b>}>
|
||||
For delete any signature first of all you need select before
|
||||
<br /> and then use <b className="text-sky-500">Del</b> or{' '}
|
||||
<b className="text-sky-500">Backspace</b>
|
||||
<br /> and then use <b className="text-sky-500">Backspace</b>
|
||||
</InfoDrawer>
|
||||
</div>
|
||||
) as React.ReactNode,
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useClipboard } from '@/hooks/Mapper/hooks/useClipboard';
|
||||
import { parseSignatures } from '@/hooks/Mapper/helpers';
|
||||
import { Commands, OutCommand } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { WdTooltip, WdTooltipHandlers } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { GROUPS_LIST } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/constants.ts';
|
||||
|
||||
import { DataTable, DataTableRowClickEvent, DataTableRowMouseEvent, SortOrder } from 'primereact/datatable';
|
||||
import { Column } from 'primereact/column';
|
||||
@@ -21,16 +22,22 @@ import {
|
||||
getRowColorByTimeLeft,
|
||||
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/helpers';
|
||||
import {
|
||||
renderDescription,
|
||||
renderIcon,
|
||||
renderInfoColumn,
|
||||
renderTimeLeft,
|
||||
renderInsertedTimeLeft,
|
||||
renderUpdatedTimeLeft,
|
||||
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/renders';
|
||||
import useLocalStorageState from 'use-local-storage-state';
|
||||
import { PrimeIcons } from 'primereact/api';
|
||||
import { SignatureSettings } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings';
|
||||
import { useMapEventListener } from '@/hooks/Mapper/events';
|
||||
import { WdTooltipWrapper } from '@/hooks/Mapper/components/ui-kit/WdTooltipWrapper';
|
||||
|
||||
import { COSMIC_SIGNATURE } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignatureSettingsDialog';
|
||||
import {
|
||||
SHOW_DESCRIPTION_COLUMN_SETTING,
|
||||
SHOW_INSERTED_COLUMN_SETTING,
|
||||
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures';
|
||||
type SystemSignaturesSortSettings = {
|
||||
sortField: string;
|
||||
sortOrder: SortOrder;
|
||||
@@ -44,10 +51,17 @@ const SORT_DEFAULT_VALUES: SystemSignaturesSortSettings = {
|
||||
interface SystemSignaturesContentProps {
|
||||
systemId: string;
|
||||
settings: Setting[];
|
||||
hideLinkedSignatures?: boolean;
|
||||
selectable?: boolean;
|
||||
onSelect?: (signature: SystemSignature) => void;
|
||||
}
|
||||
export const SystemSignaturesContent = ({ systemId, settings, selectable, onSelect }: SystemSignaturesContentProps) => {
|
||||
export const SystemSignaturesContent = ({
|
||||
systemId,
|
||||
settings,
|
||||
hideLinkedSignatures,
|
||||
selectable,
|
||||
onSelect,
|
||||
}: SystemSignaturesContentProps) => {
|
||||
const { outCommand } = useMapRootState();
|
||||
|
||||
const [signatures, setSignatures, signaturesRef] = useRefState<SystemSignature[]>([]);
|
||||
@@ -80,13 +94,41 @@ export const SystemSignaturesContent = ({ systemId, settings, selectable, onSele
|
||||
}
|
||||
}, []);
|
||||
|
||||
const groupSettings = useMemo(() => settings.filter(s => (GROUPS_LIST as string[]).includes(s.key)), [settings]);
|
||||
const showDescriptionColumn = useMemo(
|
||||
() => settings.find(s => s.key === SHOW_DESCRIPTION_COLUMN_SETTING)?.value,
|
||||
[settings],
|
||||
);
|
||||
|
||||
const showInsertedColumn = useMemo(
|
||||
() => settings.find(s => s.key === SHOW_INSERTED_COLUMN_SETTING)?.value,
|
||||
[settings],
|
||||
);
|
||||
|
||||
const filteredSignatures = useMemo(() => {
|
||||
return signatures
|
||||
.filter(x => settings.find(y => y.key === x.kind)?.value)
|
||||
.filter(x => {
|
||||
if (hideLinkedSignatures && !!x.linked_system) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const isCosmicSignature = x.kind === COSMIC_SIGNATURE;
|
||||
|
||||
if (isCosmicSignature) {
|
||||
const showCosmicSignatures = settings.find(y => y.key === COSMIC_SIGNATURE)?.value;
|
||||
if (showCosmicSignatures) {
|
||||
return !x.group || groupSettings.find(y => y.key === x.group)?.value;
|
||||
} else {
|
||||
return !!x.group && groupSettings.find(y => y.key === x.group)?.value;
|
||||
}
|
||||
}
|
||||
|
||||
return settings.find(y => y.key === x.kind)?.value;
|
||||
})
|
||||
.sort((a, b) => {
|
||||
return new Date(b.updated_at || 0).getTime() - new Date(a.updated_at || 0).getTime();
|
||||
});
|
||||
}, [signatures, settings]);
|
||||
}, [signatures, settings, groupSettings, hideLinkedSignatures]);
|
||||
|
||||
const handleGetSignatures = useCallback(async () => {
|
||||
const { signatures } = await outCommand({
|
||||
@@ -98,26 +140,6 @@ export const SystemSignaturesContent = ({ systemId, settings, selectable, onSele
|
||||
setSignatures(signatures);
|
||||
}, [outCommand, systemId]);
|
||||
|
||||
// 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,
|
||||
// },
|
||||
// });
|
||||
|
||||
// setSignatures(() => updatedSignatures);
|
||||
// setSelectedSignatures([]);
|
||||
// },
|
||||
// [outCommand, systemId],
|
||||
// );
|
||||
|
||||
const handleUpdateSignatures = useCallback(
|
||||
async (newSignatures: SystemSignature[], updateOnly: boolean) => {
|
||||
const { added, updated, removed } = getActualSigs(signaturesRef.current, newSignatures, updateOnly);
|
||||
@@ -181,7 +203,7 @@ export const SystemSignaturesContent = ({ systemId, settings, selectable, onSele
|
||||
|
||||
useHotkey(true, ['a'], handleSelectAll);
|
||||
|
||||
useHotkey(false, ['Backspace', 'Delete'], handleDeleteSelected);
|
||||
useHotkey(false, ['Backspace'], handleDeleteSelected);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectable) {
|
||||
@@ -345,22 +367,46 @@ export const SystemSignaturesContent = ({ systemId, settings, selectable, onSele
|
||||
style={{ maxWidth: nameColumnWidth }}
|
||||
hidden={compact || medium}
|
||||
></Column>
|
||||
{showDescriptionColumn && (
|
||||
<Column
|
||||
field="description"
|
||||
header="Description"
|
||||
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
|
||||
body={renderDescription}
|
||||
hidden={compact}
|
||||
sortable
|
||||
></Column>
|
||||
)}
|
||||
|
||||
{showInsertedColumn && (
|
||||
<Column
|
||||
field="inserted_at"
|
||||
header="Inserted"
|
||||
dataType="date"
|
||||
bodyClassName="w-[70px] text-ellipsis overflow-hidden whitespace-nowrap"
|
||||
body={renderInsertedTimeLeft}
|
||||
sortable
|
||||
></Column>
|
||||
)}
|
||||
|
||||
<Column
|
||||
field="updated_at"
|
||||
header="Updated"
|
||||
dataType="date"
|
||||
bodyClassName="w-[70px] text-ellipsis overflow-hidden whitespace-nowrap"
|
||||
body={renderTimeLeft}
|
||||
body={renderUpdatedTimeLeft}
|
||||
sortable
|
||||
></Column>
|
||||
|
||||
<Column
|
||||
bodyClassName="p-0 pl-1 pr-2"
|
||||
field="group"
|
||||
body={renderToolbar}
|
||||
// headerClassName={headerClasses}
|
||||
style={{ maxWidth: 26, minWidth: 26, width: 26 }}
|
||||
></Column>
|
||||
{!selectable && (
|
||||
<Column
|
||||
bodyClassName="p-0 pl-1 pr-2"
|
||||
field="group"
|
||||
body={renderToolbar}
|
||||
// headerClassName={headerClasses}
|
||||
style={{ maxWidth: 26, minWidth: 26, width: 26 }}
|
||||
></Column>
|
||||
)}
|
||||
</DataTable>
|
||||
</>
|
||||
)}
|
||||
@@ -370,12 +416,14 @@ export const SystemSignaturesContent = ({ systemId, settings, selectable, onSele
|
||||
content={hoveredSig ? <SignatureView {...hoveredSig} /> : null}
|
||||
/>
|
||||
|
||||
<SignatureSettings
|
||||
systemId={systemId}
|
||||
show={showSignatureSettings}
|
||||
onHide={() => setShowSignatureSettings(false)}
|
||||
signatureData={selectedSignature}
|
||||
/>
|
||||
{showSignatureSettings && (
|
||||
<SignatureSettings
|
||||
systemId={systemId}
|
||||
show
|
||||
onHide={() => setShowSignatureSettings(false)}
|
||||
signatureData={selectedSignature}
|
||||
/>
|
||||
)}
|
||||
|
||||
{askUser && (
|
||||
<div className="absolute left-[1px] top-[29px] h-[calc(100%-30px)] w-[calc(100%-3px)] bg-stone-900/10 backdrop-blur-sm">
|
||||
|
||||
@@ -19,6 +19,8 @@ export const getActualSigs = (
|
||||
const isNeedUpgrade = getState(GROUPS_LIST, newSig) > getState(GROUPS_LIST, oldSig);
|
||||
if (isNeedUpgrade) {
|
||||
updated.push({ ...oldSig, group: newSig.group, name: newSig.name });
|
||||
} else {
|
||||
updated.push({ ...oldSig });
|
||||
}
|
||||
} else {
|
||||
if (!updateOnly) {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
export * from './renderIcon';
|
||||
export * from './renderDescription';
|
||||
export * from './renderName';
|
||||
export * from './renderTimeLeft';
|
||||
export * from './renderInsertedTimeLeft';
|
||||
export * from './renderUpdatedTimeLeft';
|
||||
export * from './renderLinkedSystem';
|
||||
export * from './renderInfoColumn';
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { SystemSignature } from '@/hooks/Mapper/types';
|
||||
|
||||
export const renderDescription = (row: SystemSignature) => {
|
||||
return <span title={row?.description}>{row?.description}</span>;
|
||||
};
|
||||
@@ -1,5 +1,9 @@
|
||||
import { PrimeIcons } from 'primereact/api';
|
||||
import { SignatureGroup, SystemSignature } from '@/hooks/Mapper/types';
|
||||
import { SystemViewStandalone, WHClassView } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
import { WdTooltipWrapper } from '@/hooks/Mapper/components/ui-kit/WdTooltipWrapper';
|
||||
|
||||
import clsx from 'clsx';
|
||||
import { renderName } from './renderName.tsx';
|
||||
import classes from './renderInfoColumn.module.scss';
|
||||
@@ -32,13 +36,23 @@ export const renderInfoColumn = (row: SystemSignature) => {
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
{row.description && (
|
||||
<WdTooltipWrapper content={row.description}>
|
||||
<span className={clsx(PrimeIcons.EXCLAMATION_CIRCLE, 'text-[12px]')}></span>
|
||||
</WdTooltipWrapper>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (row.description != null && row.description.length > 0) {
|
||||
return <span title={row.description}>{row.description}</span>;
|
||||
}
|
||||
|
||||
return renderName(row);
|
||||
return (
|
||||
<div className="flex gap-1 items-center">
|
||||
{renderName(row)}{' '}
|
||||
{row.description && (
|
||||
<WdTooltipWrapper content={row.description}>
|
||||
<span className={clsx(PrimeIcons.EXCLAMATION_CIRCLE, 'text-[12px]')}></span>
|
||||
</WdTooltipWrapper>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { SystemSignature } from '@/hooks/Mapper/types';
|
||||
import { TimeLeft } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
export const renderInsertedTimeLeft = (row: SystemSignature) => {
|
||||
return (
|
||||
<div className="flex w-full items-center">
|
||||
<TimeLeft cDate={row.inserted_at ? new Date(row.inserted_at) : undefined} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
import { SystemSignature } from '@/hooks/Mapper/types';
|
||||
import { TimeLeft } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
export const renderTimeLeft = (row: SystemSignature) => {
|
||||
export const renderUpdatedTimeLeft = (row: SystemSignature) => {
|
||||
return (
|
||||
<div className="flex w-full items-center">
|
||||
<TimeLeft cDate={row.updated_at ? new Date(row.updated_at) : undefined} />
|
||||
@@ -7,13 +7,13 @@ import { useCallback, useState } from 'react';
|
||||
import { OnTheMap, RightBar } from '@/hooks/Mapper/components/mapRootContent/components';
|
||||
import { MapContextMenu } from '@/hooks/Mapper/components/mapRootContent/components/MapContextMenu/MapContextMenu.tsx';
|
||||
import { useSkipContextMenu } from '@/hooks/Mapper/hooks/useSkipContextMenu';
|
||||
import { MapSettings } from "@/hooks/Mapper/components/mapRootContent/components/MapSettings";
|
||||
import { MapSettings } from '@/hooks/Mapper/components/mapRootContent/components/MapSettings';
|
||||
|
||||
export interface MapRootContentProps {}
|
||||
|
||||
// eslint-disable-next-line no-empty-pattern
|
||||
export const MapRootContent = ({}: MapRootContentProps) => {
|
||||
const { mapRef, interfaceSettings } = useMapRootState();
|
||||
const { interfaceSettings } = useMapRootState();
|
||||
const { isShowMenu } = interfaceSettings;
|
||||
|
||||
const [showOnTheMap, setShowOnTheMap] = useState(false);
|
||||
@@ -26,7 +26,7 @@ export const MapRootContent = ({}: MapRootContentProps) => {
|
||||
useSkipContextMenu();
|
||||
|
||||
return (
|
||||
<Layout map={<MapWrapper refn={mapRef} />}>
|
||||
<Layout map={<MapWrapper />}>
|
||||
{!isShowMenu ? (
|
||||
<div className="absolute top-0 left-14 w-[calc(100%-3.5rem)] h-[calc(100%-3.5rem)] pointer-events-none">
|
||||
<div className="absolute top-0 left-0 w-[calc(100%-3.5rem)] h-full pointer-events-none">
|
||||
|
||||
@@ -61,6 +61,7 @@ const CONNECTIONS_CHECKBOXES_PROPS: CheckboxesList = [
|
||||
|
||||
const UI_CHECKBOXES_PROPS: CheckboxesList = [
|
||||
{ prop: InterfaceStoredSettingsProps.isShowMenu, label: 'Enable compact map menu bar' },
|
||||
{ prop: InterfaceStoredSettingsProps.isThickConnections, label: 'Thicker connections' },
|
||||
];
|
||||
|
||||
export const MapSettings = ({ show, onHide }: MapSettingsProps) => {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { Map } from '@/hooks/Mapper/components/map/Map.tsx';
|
||||
import { ForwardedRef, useCallback, useRef, useState } from 'react';
|
||||
import { MapHandlers, OutCommand, OutCommandHandler, SolarSystemConnection } from '@/hooks/Mapper/types';
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
import { OutCommand, OutCommandHandler, SolarSystemConnection } from '@/hooks/Mapper/types';
|
||||
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,
|
||||
SystemLinkSignatureDialog,
|
||||
SystemSettingsDialog,
|
||||
} from '@/hooks/Mapper/components/mapInterface/components';
|
||||
import classes from './MapWrapper.module.scss';
|
||||
import { Connections } from '@/hooks/Mapper/components/mapRootContent/components/Connections';
|
||||
@@ -20,25 +20,45 @@ 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 {
|
||||
refn: ForwardedRef<MapHandlers>;
|
||||
}
|
||||
import { useDeleteSystems } from '@/hooks/Mapper/components/contexts/hooks';
|
||||
import { useCommonMapEventProcessor } from '@/hooks/Mapper/components/mapWrapper/hooks/useCommonMapEventProcessor.ts';
|
||||
|
||||
// TODO: INFO - this component needs for abstract work with Map instance
|
||||
export const MapWrapper = ({ refn }: MapWrapperProps) => {
|
||||
export const MapWrapper = () => {
|
||||
const {
|
||||
update,
|
||||
outCommand,
|
||||
data: { selectedConnections, selectedSystems, hubs, systems },
|
||||
interfaceSettings: { isShowMenu, isShowMinimap = STORED_INTERFACE_DEFAULT_VALUES.isShowMinimap, isShowKSpace },
|
||||
interfaceSettings: {
|
||||
isShowMenu,
|
||||
isShowMinimap = STORED_INTERFACE_DEFAULT_VALUES.isShowMinimap,
|
||||
isShowKSpace,
|
||||
isThickConnections,
|
||||
},
|
||||
} = useMapRootState();
|
||||
const { deleteSystems } = useDeleteSystems();
|
||||
const { mapRef, runCommand } = useCommonMapEventProcessor();
|
||||
|
||||
const { open, ...systemContextProps } = useContextMenuSystemHandlers({ systems, hubs, outCommand });
|
||||
const { handleSystemMultipleContext, ...systemMultipleCtxProps } = useContextMenuSystemMultipleHandlers();
|
||||
|
||||
const ref = useRef({ selectedConnections, selectedSystems, systemContextProps, systems });
|
||||
ref.current = { selectedConnections, selectedSystems, systemContextProps, systems };
|
||||
const [openSettings, setOpenSettings] = useState<string | null>(null);
|
||||
const [openLinkSignatures, setOpenLinkSignatures] = useState<any | null>(null);
|
||||
const [openCustomLabel, setOpenCustomLabel] = useState<string | null>(null);
|
||||
const [selectedConnection, setSelectedConnection] = useState<SolarSystemConnection | null>(null);
|
||||
|
||||
const ref = useRef({ selectedConnections, selectedSystems, systemContextProps, systems, deleteSystems });
|
||||
ref.current = { selectedConnections, selectedSystems, systemContextProps, systems, deleteSystems };
|
||||
|
||||
useMapEventListener(event => {
|
||||
switch (event.name) {
|
||||
case Commands.linkSignatureToSystem:
|
||||
setOpenLinkSignatures(event.data);
|
||||
return true;
|
||||
}
|
||||
|
||||
runCommand(event);
|
||||
});
|
||||
|
||||
const onSelectionChange: OnMapSelectionChange = useCallback(
|
||||
({ systems, connections }) => {
|
||||
@@ -59,9 +79,6 @@ export const MapWrapper = ({ refn }: MapWrapperProps) => {
|
||||
[update],
|
||||
);
|
||||
|
||||
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 => {
|
||||
switch (event.type) {
|
||||
@@ -95,22 +112,19 @@ export const MapWrapper = ({ refn }: MapWrapperProps) => {
|
||||
[open],
|
||||
);
|
||||
|
||||
const [selectedConnection, setSelectedConnection] = useState<SolarSystemConnection | null>(null);
|
||||
|
||||
const handleConnectionDbClick = useCallback((e: SolarSystemConnection) => setSelectedConnection(e), []);
|
||||
|
||||
useMapEventListener(event => {
|
||||
switch (event.name) {
|
||||
case Commands.linkSignatureToSystem:
|
||||
setOpenLinkSignatures(event.data);
|
||||
return true;
|
||||
const handleManualDelete = useCallback((toDelete: string[]) => {
|
||||
const restDel = toDelete.filter(x => ref.current.systems.some(y => y.id === x));
|
||||
if (restDel.length > 0) {
|
||||
ref.current.deleteSystems(restDel);
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Map
|
||||
ref={refn}
|
||||
ref={mapRef}
|
||||
onCommand={handleCommand}
|
||||
onSelectionChange={onSelectionChange}
|
||||
onConnectionInfoClick={handleConnectionDbClick}
|
||||
@@ -119,6 +133,8 @@ export const MapWrapper = ({ refn }: MapWrapperProps) => {
|
||||
minimapClasses={!isShowMenu ? classes.MiniMap : undefined}
|
||||
isShowMinimap={isShowMinimap}
|
||||
showKSpaceBG={isShowKSpace}
|
||||
onManualDelete={handleManualDelete}
|
||||
isThickConnections={isThickConnections}
|
||||
/>
|
||||
|
||||
{openSettings != null && (
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { MutableRefObject, useCallback, useEffect, useRef } from 'react';
|
||||
import { Command, Commands, MapHandlers } from '@/hooks/Mapper/types';
|
||||
import { MapEvent } from '@/hooks/Mapper/events';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
|
||||
export const useCommonMapEventProcessor = () => {
|
||||
const mapRef = useRef<MapHandlers>() as MutableRefObject<MapHandlers>;
|
||||
const {
|
||||
data: { systems },
|
||||
} = useMapRootState();
|
||||
|
||||
const refQueue = useRef<MapEvent<Command>[]>([]);
|
||||
|
||||
// const ref = useRef({})
|
||||
|
||||
const runCommand = useCallback(({ name, data }: MapEvent<Command>) => {
|
||||
switch (name) {
|
||||
case Commands.addSystems:
|
||||
case Commands.removeSystems:
|
||||
// case Commands.addConnections:
|
||||
refQueue.current.push({ name, data });
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-ignore hz why here type error
|
||||
mapRef.current?.command(name, data);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
refQueue.current.forEach(x => mapRef.current?.command(x.name, x.data));
|
||||
refQueue.current = [];
|
||||
}, [systems]);
|
||||
|
||||
return {
|
||||
mapRef,
|
||||
runCommand,
|
||||
};
|
||||
};
|
||||
@@ -4,7 +4,7 @@ import classes from './CharacterCard.module.scss';
|
||||
import { SystemView } from '@/hooks/Mapper/components/ui-kit/SystemView';
|
||||
import { CharacterTypeRaw, WithIsOwnCharacter } from '@/hooks/Mapper/types';
|
||||
import { Commands } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { emitMapEvent } from '@/hooks/Mapper/events';
|
||||
|
||||
type CharacterCardProps = {
|
||||
compact?: boolean;
|
||||
@@ -34,11 +34,12 @@ export const CharacterCard = ({
|
||||
useSystemsCache,
|
||||
...char
|
||||
}: CharacterCardProps) => {
|
||||
const { mapRef } = useMapRootState();
|
||||
|
||||
const handleSelect = useCallback(() => {
|
||||
mapRef.current?.command(Commands.centerSystem, char?.location?.solar_system_id?.toString());
|
||||
}, [mapRef, char]);
|
||||
emitMapEvent({
|
||||
name: Commands.centerSystem,
|
||||
data: char?.location?.solar_system_id?.toString(),
|
||||
});
|
||||
}, [char]);
|
||||
|
||||
return (
|
||||
<div className={clsx(classes.CharacterCard, 'w-full text-xs', 'flex flex-col box-border')} onClick={handleSelect}>
|
||||
|
||||
@@ -31,24 +31,26 @@ export enum InterfaceStoredSettingsProps {
|
||||
isShowMenu = 'isShowMenu',
|
||||
isShowMinimap = 'isShowMinimap',
|
||||
isShowKSpace = 'isShowKSpace',
|
||||
isThickConnections = 'isThickConnections',
|
||||
}
|
||||
|
||||
export type InterfaceStoredSettings = {
|
||||
isShowMenu: boolean;
|
||||
isShowMinimap: boolean;
|
||||
isShowKSpace: boolean;
|
||||
isThickConnections: boolean;
|
||||
};
|
||||
|
||||
export const STORED_INTERFACE_DEFAULT_VALUES: InterfaceStoredSettings = {
|
||||
isShowMenu: false,
|
||||
isShowMinimap: true,
|
||||
isShowKSpace: false,
|
||||
isThickConnections: false,
|
||||
};
|
||||
|
||||
export interface MapRootContextProps {
|
||||
update: ContextStoreDataUpdate<MapRootData>;
|
||||
data: MapRootData;
|
||||
mapRef: RefObject<MapHandlers>;
|
||||
outCommand: OutCommandHandler;
|
||||
interfaceSettings: InterfaceStoredSettings;
|
||||
setInterfaceSettings: Dispatch<SetStateAction<InterfaceStoredSettings>>;
|
||||
@@ -57,7 +59,6 @@ export interface MapRootContextProps {
|
||||
const MapRootContext = createContext<MapRootContextProps>({
|
||||
update: () => {},
|
||||
data: { ...INITIAL_DATA },
|
||||
mapRef: { current: null },
|
||||
// @ts-ignore
|
||||
outCommand: async () => void 0,
|
||||
interfaceSettings: STORED_INTERFACE_DEFAULT_VALUES,
|
||||
@@ -67,7 +68,6 @@ const MapRootContext = createContext<MapRootContextProps>({
|
||||
type MapRootProviderProps = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
fwdRef: ForwardedRef<any>;
|
||||
mapRef: RefObject<MapHandlers>;
|
||||
outCommand: OutCommandHandler;
|
||||
} & WithChildren;
|
||||
|
||||
@@ -78,7 +78,7 @@ const MapRootHandlers = forwardRef(({ children }: WithChildren, fwdRef: Forwarde
|
||||
});
|
||||
|
||||
// eslint-disable-next-line react/display-name
|
||||
export const MapRootProvider = ({ children, fwdRef, mapRef, outCommand }: MapRootProviderProps) => {
|
||||
export const MapRootProvider = ({ children, fwdRef, outCommand }: MapRootProviderProps) => {
|
||||
const { update, ref } = useContextStore<MapRootData>({ ...INITIAL_DATA });
|
||||
|
||||
const [interfaceSettings, setInterfaceSettings] = useLocalStorageState<InterfaceStoredSettings>(
|
||||
@@ -94,7 +94,6 @@ export const MapRootProvider = ({ children, fwdRef, mapRef, outCommand }: MapRoo
|
||||
update,
|
||||
data: ref,
|
||||
outCommand: outCommand,
|
||||
mapRef: mapRef,
|
||||
setInterfaceSettings,
|
||||
interfaceSettings,
|
||||
}}
|
||||
|
||||
@@ -44,87 +44,79 @@ export const useMapRootHandlers = (ref: ForwardedRef<MapHandlers>) => {
|
||||
return {
|
||||
command(type, data) {
|
||||
switch (type) {
|
||||
case Commands.init:
|
||||
case Commands.init: // USED
|
||||
mapInit(data as CommandInit);
|
||||
break;
|
||||
case Commands.addSystems:
|
||||
case Commands.addSystems: // USED
|
||||
addSystems(data as CommandAddSystems);
|
||||
setTimeout(() => {
|
||||
emitMapEvent({ name: Commands.addSystems, data });
|
||||
}, 100);
|
||||
break;
|
||||
case Commands.updateSystems:
|
||||
case Commands.updateSystems: // USED
|
||||
updateSystems(data as CommandUpdateSystems);
|
||||
break;
|
||||
case Commands.removeSystems:
|
||||
case Commands.removeSystems: // USED
|
||||
removeSystems(data as CommandRemoveSystems);
|
||||
setTimeout(() => {
|
||||
emitMapEvent({ name: Commands.removeSystems, data });
|
||||
}, 100);
|
||||
|
||||
break;
|
||||
case Commands.addConnections:
|
||||
case Commands.addConnections: // USED
|
||||
addConnections(data as CommandAddConnections);
|
||||
setTimeout(() => {
|
||||
emitMapEvent({ name: Commands.addConnections, data });
|
||||
}, 100);
|
||||
break;
|
||||
case Commands.removeConnections:
|
||||
case Commands.removeConnections: // USED
|
||||
removeConnections(data as CommandRemoveConnections);
|
||||
break;
|
||||
case Commands.updateConnection:
|
||||
case Commands.updateConnection: // USED
|
||||
updateConnection(data as CommandUpdateConnection);
|
||||
break;
|
||||
case Commands.charactersUpdated:
|
||||
case Commands.charactersUpdated: // USED
|
||||
charactersUpdated(data as CommandCharactersUpdated);
|
||||
break;
|
||||
case Commands.characterAdded:
|
||||
case Commands.characterAdded: // USED
|
||||
characterAdded(data as CommandCharacterAdded);
|
||||
break;
|
||||
case Commands.characterRemoved:
|
||||
case Commands.characterRemoved: // USED
|
||||
characterRemoved(data as CommandCharacterRemoved);
|
||||
break;
|
||||
case Commands.characterUpdated:
|
||||
case Commands.characterUpdated: // USED
|
||||
characterUpdated(data as CommandCharacterUpdated);
|
||||
break;
|
||||
case Commands.presentCharacters:
|
||||
case Commands.presentCharacters: // USED
|
||||
presentCharacters(data as CommandPresentCharacters);
|
||||
break;
|
||||
case Commands.mapUpdated:
|
||||
case Commands.mapUpdated: // USED
|
||||
mapUpdated(data as CommandMapUpdated);
|
||||
break;
|
||||
case Commands.routes:
|
||||
mapRoutes(data as CommandRoutes);
|
||||
break;
|
||||
|
||||
case Commands.centerSystem:
|
||||
case Commands.centerSystem: // USED
|
||||
// do nothing here
|
||||
break;
|
||||
|
||||
case Commands.selectSystem:
|
||||
case Commands.selectSystem: // USED
|
||||
// do nothing here
|
||||
break;
|
||||
|
||||
case Commands.linkSignatureToSystem:
|
||||
// TODO command data type lost
|
||||
// @ts-ignore
|
||||
emitMapEvent({ name: Commands.linkSignatureToSystem, data });
|
||||
break;
|
||||
// case Commands.linkSignatureToSystem:
|
||||
// // TODO command data type lost
|
||||
// // @ts-ignore
|
||||
// emitMapEvent({ name: Commands.linkSignatureToSystem, data });
|
||||
// break;
|
||||
|
||||
case Commands.killsUpdated:
|
||||
// do nothing here
|
||||
break;
|
||||
|
||||
case Commands.signaturesUpdated:
|
||||
// TODO command data type lost
|
||||
// @ts-ignore
|
||||
emitMapEvent({ name: Commands.signaturesUpdated, data });
|
||||
break;
|
||||
// case Commands.signaturesUpdated:
|
||||
// // TODO command data type lost
|
||||
// // @ts-ignore
|
||||
// emitMapEvent({ name: Commands.signaturesUpdated, data });
|
||||
// break;
|
||||
|
||||
default:
|
||||
console.warn(`JOipP Interface handlers: Unknown command: ${type}`, data);
|
||||
break;
|
||||
}
|
||||
|
||||
emitMapEvent({ name: type, data });
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
@@ -25,5 +25,6 @@ export type SystemSignature = {
|
||||
group: SignatureGroup;
|
||||
type: string;
|
||||
linked_system?: SolarSystemStaticInfoRaw;
|
||||
inserted_at?: string;
|
||||
updated_at?: string;
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { RefObject, useCallback } from 'react';
|
||||
|
||||
import { MapHandlers } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { getQueryVariable } from './utils';
|
||||
|
||||
export const useMapperHandlers = (handlerRefs: RefObject<MapHandlers>[], hooksRef: RefObject<any>) => {
|
||||
const handleCommand = useCallback(
|
||||
@@ -16,10 +15,6 @@ export const useMapperHandlers = (handlerRefs: RefObject<MapHandlers>[], hooksRe
|
||||
);
|
||||
|
||||
const handleMapEvent = useCallback(({ type, body }) => {
|
||||
if (getQueryVariable('debug') === 'true') {
|
||||
console.log(type, body);
|
||||
}
|
||||
|
||||
handlerRefs.forEach(ref => {
|
||||
if (!ref.current) {
|
||||
return;
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
"react-grid-layout": "^1.3.4",
|
||||
"react-hook-form": "^7.53.1",
|
||||
"react-usestateref": "^1.0.9",
|
||||
"reactflow": "^11.10.4",
|
||||
"reactflow": "^11.11.4",
|
||||
"rxjs": "^7.8.1",
|
||||
"tailwindcss": "^3.3.6",
|
||||
"topbar": "^3.0.0",
|
||||
|
||||
@@ -3280,9 +3280,9 @@ react@18.2.0:
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
reactflow@^11.10.4:
|
||||
reactflow@^11.11.4:
|
||||
version "11.11.4"
|
||||
resolved "https://registry.npmjs.org/reactflow/-/reactflow-11.11.4.tgz"
|
||||
resolved "https://registry.yarnpkg.com/reactflow/-/reactflow-11.11.4.tgz#e3593e313420542caed81aecbd73fb9bc6576653"
|
||||
integrity sha512-70FOtJkUWH3BAOsN+LU9lCrKoKbtOPnz2uq0CV2PLdNSwxTXOhCbsZr50GmZ+Rtw3jx8Uv7/vBFtCGixLfd4Og==
|
||||
dependencies:
|
||||
"@reactflow/background" "11.3.14"
|
||||
|
||||
@@ -12,6 +12,7 @@ defmodule WandererApp.Api.MapSystem do
|
||||
|
||||
code_interface do
|
||||
define(:create, action: :create)
|
||||
define(:destroy, action: :destroy)
|
||||
|
||||
define(:by_id,
|
||||
get_by: [:id],
|
||||
|
||||
@@ -16,6 +16,7 @@ defmodule WandererApp.Api.MapSystemSignature do
|
||||
define(:update, action: :update)
|
||||
define(:update_linked_system, action: :update_linked_system)
|
||||
define(:update_type, action: :update_type)
|
||||
define(:update_group, action: :update_group)
|
||||
|
||||
define(:by_id,
|
||||
get_by: [:id],
|
||||
@@ -71,7 +72,8 @@ defmodule WandererApp.Api.MapSystemSignature do
|
||||
:description,
|
||||
:kind,
|
||||
:group,
|
||||
:type
|
||||
:type,
|
||||
:updated
|
||||
]
|
||||
|
||||
primary? true
|
||||
@@ -86,6 +88,10 @@ defmodule WandererApp.Api.MapSystemSignature do
|
||||
accept [:type]
|
||||
end
|
||||
|
||||
update :update_group do
|
||||
accept [:group]
|
||||
end
|
||||
|
||||
read :by_system_id do
|
||||
argument(:system_id, :string, allow_nil?: false)
|
||||
|
||||
@@ -123,6 +129,8 @@ defmodule WandererApp.Api.MapSystemSignature do
|
||||
attribute :kind, :string
|
||||
attribute :group, :string
|
||||
|
||||
attribute :updated, :integer
|
||||
|
||||
create_timestamp(:inserted_at)
|
||||
update_timestamp(:updated_at)
|
||||
end
|
||||
|
||||
@@ -1878,6 +1878,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
position_y: position.y
|
||||
})
|
||||
|> WandererApp.MapSystemRepo.cleanup_labels!(map_opts)
|
||||
|> WandererApp.MapSystemRepo.update_visible!(%{visible: true})
|
||||
|> WandererApp.MapSystemRepo.cleanup_tags()
|
||||
|
||||
@ddrt.insert(
|
||||
@@ -1895,8 +1896,9 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
ttl: @system_inactive_timeout
|
||||
)
|
||||
|
||||
broadcast!(map_id, :add_system, updated_system)
|
||||
WandererApp.Map.add_system(map_id, updated_system)
|
||||
broadcast!(map_id, :add_system, updated_system)
|
||||
:ok
|
||||
|
||||
_ ->
|
||||
{:ok, solar_system_info} =
|
||||
@@ -1923,11 +1925,13 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
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)
|
||||
|
||||
:ok
|
||||
|
||||
error ->
|
||||
@logger.debug("Failed to create system: #{inspect(error, pretty: true)}")
|
||||
@logger.warning("Failed to create system: #{inspect(error, pretty: true)}")
|
||||
:ok
|
||||
end
|
||||
end
|
||||
|
||||
@@ -237,7 +237,7 @@ defmodule WandererApp.Map.SubscriptionManager do
|
||||
defp _renew_subscription(%{auto_renew?: true} = subscription) when is_map(subscription) do
|
||||
with {:ok, %{map: map}} <-
|
||||
subscription |> WandererApp.MapSubscriptionRepo.load_relationships([:map]),
|
||||
{:ok, estimated_price} <- estimate_price(subscription, true),
|
||||
{:ok, estimated_price, discount} <- estimate_price(subscription, true),
|
||||
{:ok, map_balance} <- get_balance(map) do
|
||||
case map_balance >= estimated_price do
|
||||
true ->
|
||||
@@ -245,7 +245,7 @@ defmodule WandererApp.Map.SubscriptionManager do
|
||||
WandererApp.MapTransactionRepo.create(%{
|
||||
map_id: map.id,
|
||||
user_id: nil,
|
||||
amount: estimated_price,
|
||||
amount: estimated_price - discount,
|
||||
type: :out
|
||||
})
|
||||
|
||||
@@ -267,7 +267,7 @@ defmodule WandererApp.Map.SubscriptionManager do
|
||||
|
||||
:telemetry.execute([:wanderer_app, :map, :subscription, :renew], %{count: 1}, %{
|
||||
map_id: map.id,
|
||||
amount: estimated_price
|
||||
amount: estimated_price - discount
|
||||
})
|
||||
|
||||
:ok
|
||||
|
||||
@@ -144,8 +144,13 @@ defmodule WandererAppWeb.MapSignaturesEventHandler do
|
||||
updated = updated_signatures |> Enum.find(fn u -> u.eve_id == s.eve_id end)
|
||||
|
||||
if not is_nil(updated) do
|
||||
IO.puts("Updating #{s.eve_id}")
|
||||
|
||||
s
|
||||
|> WandererApp.Api.MapSystemSignature.update(updated)
|
||||
|> WandererApp.Api.MapSystemSignature.update(
|
||||
updated
|
||||
|> Map.put(:updated, System.os_time())
|
||||
)
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -225,6 +230,7 @@ defmodule WandererAppWeb.MapSignaturesEventHandler do
|
||||
|> Enum.filter(fn s -> s.eve_id == signature_eve_id end)
|
||||
|> Enum.each(fn s ->
|
||||
s
|
||||
|> WandererApp.Api.MapSystemSignature.update_group!(%{group: "Wormhole"})
|
||||
|> WandererApp.Api.MapSystemSignature.update_linked_system(%{
|
||||
linked_system_id: solar_system_target
|
||||
})
|
||||
@@ -312,7 +318,11 @@ defmodule WandererAppWeb.MapSignaturesEventHandler do
|
||||
do:
|
||||
system_id
|
||||
|> WandererApp.Api.MapSystemSignature.by_system_id!()
|
||||
|> Enum.map(fn %{updated_at: updated_at, linked_system_id: linked_system_id} = s ->
|
||||
|> Enum.map(fn %{
|
||||
inserted_at: inserted_at,
|
||||
updated_at: updated_at,
|
||||
linked_system_id: linked_system_id
|
||||
} = s ->
|
||||
s
|
||||
|> Map.take([
|
||||
:eve_id,
|
||||
@@ -320,10 +330,10 @@ defmodule WandererAppWeb.MapSignaturesEventHandler do
|
||||
:description,
|
||||
:kind,
|
||||
:group,
|
||||
:type,
|
||||
:updated_at
|
||||
:type
|
||||
])
|
||||
|> Map.put(:linked_system, MapEventHandler.get_system_static_info(linked_system_id))
|
||||
|> Map.put(:inserted_at, inserted_at |> Calendar.strftime("%Y/%m/%d %H:%M:%S"))
|
||||
|> Map.put(:updated_at, updated_at |> Calendar.strftime("%Y/%m/%d %H:%M:%S"))
|
||||
end)
|
||||
|
||||
|
||||
2
mix.exs
2
mix.exs
@@ -2,7 +2,7 @@ defmodule WandererApp.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
@source_url "https://github.com/wanderer-industries/wanderer"
|
||||
@version "1.15.5"
|
||||
@version "1.19.0"
|
||||
|
||||
def project do
|
||||
[
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
defmodule WandererApp.Repo.Migrations.AddSignatureUpdated 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 :updated, :bigint
|
||||
end
|
||||
end
|
||||
|
||||
def down do
|
||||
alter table(:map_system_signatures_v1) do
|
||||
remove :updated
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,187 @@
|
||||
{
|
||||
"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": "type",
|
||||
"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?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "updated",
|
||||
"type": "bigint"
|
||||
},
|
||||
{
|
||||
"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": "6A255286EC34371C26500578C2B991D604C154AB4751B8F1EFBE4E7E61AA6F2D",
|
||||
"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"
|
||||
}
|
||||
Reference in New Issue
Block a user