mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-11-03 16:07:25 +00:00
Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5c8c05426 | ||
|
|
b6bb4647c7 | ||
|
|
a81f06b743 | ||
|
|
cb41a33546 | ||
|
|
005068de9c | ||
|
|
d8c7b1e070 | ||
|
|
4835dfcc42 | ||
|
|
15bceb09a2 | ||
|
|
13e818abfd | ||
|
|
9c5f6049b5 | ||
|
|
2095b619a4 | ||
|
|
df155cbc1b | ||
|
|
3781729fd1 | ||
|
|
d03c634ec0 | ||
|
|
93c979c218 | ||
|
|
90fef94583 | ||
|
|
0b8eec2263 | ||
|
|
9511af4e6d | ||
|
|
7deaf1fd9f | ||
|
|
43cc5bd520 | ||
|
|
68b58aa520 | ||
|
|
dbadd09af3 | ||
|
|
fcbe2c754f | ||
|
|
ad4580677b | ||
|
|
01a6cc7d92 | ||
|
|
95ce95a187 | ||
|
|
ce8e6fbfb0 | ||
|
|
a20eaed76b | ||
|
|
419af72028 | ||
|
|
8e499522f6 | ||
|
|
84321b847e | ||
|
|
c969a4d465 | ||
|
|
0e12c850b6 | ||
|
|
442835dd9b | ||
|
|
b4ff99cb2e | ||
|
|
aa0ecbc998 | ||
|
|
cc412e93c0 | ||
|
|
1d36fadbfa | ||
|
|
56182bd87d | ||
|
|
d290ff92b3 | ||
|
|
298c5fd3b8 | ||
|
|
e365c43781 | ||
|
|
23a9f22ef4 | ||
|
|
242f437237 | ||
|
|
2eae8cffdb | ||
|
|
68ab3d4f72 | ||
|
|
1ea805aff0 | ||
|
|
6ce45349dc | ||
|
|
8f20cd9863 | ||
|
|
4ed0e85680 | ||
|
|
8ce9eb9955 | ||
|
|
363330f3d1 | ||
|
|
fbf9c5ddd6 | ||
|
|
fbf2ee314c | ||
|
|
c9f83fb419 | ||
|
|
9737d91e16 | ||
|
|
2f672ae970 | ||
|
|
25339546c6 | ||
|
|
912cad42ac | ||
|
|
b3752c8d8f | ||
|
|
e8a11333f2 | ||
|
|
8bb6d09e6e | ||
|
|
56bf955297 | ||
|
|
ef6c08dfe8 | ||
|
|
495c3e1cd7 | ||
|
|
9a5fe3d744 | ||
|
|
72607cae4d | ||
|
|
4891cdb04d |
149
CHANGELOG.md
149
CHANGELOG.md
@@ -2,11 +2,123 @@
|
||||
|
||||
<!-- changelog -->
|
||||
|
||||
## [v1.3.1](https://github.com/wanderer-industries/wanderer/compare/v1.3.0...v1.3.1) (2024-10-07)
|
||||
## [v1.12.7](https://github.com/wanderer-industries/wanderer/compare/v1.12.6...v1.12.7) (2024-10-24)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.12.6](https://github.com/wanderer-industries/wanderer/compare/v1.12.5...v1.12.6) (2024-10-24)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.12.5](https://github.com/wanderer-industries/wanderer/compare/v1.12.4...v1.12.5) (2024-10-22)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.12.4](https://github.com/wanderer-industries/wanderer/compare/v1.12.3...v1.12.4) (2024-10-21)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Map: Fix systems cleanup
|
||||
|
||||
## [v1.12.3](https://github.com/wanderer-industries/wanderer/compare/v1.12.2...v1.12.3) (2024-10-18)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Map: Fix regression issues
|
||||
|
||||
## [v1.12.2](https://github.com/wanderer-industries/wanderer/compare/v1.12.1...v1.12.2) (2024-10-16)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.12.1](https://github.com/wanderer-industries/wanderer/compare/v1.12.0...v1.12.1) (2024-10-16)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Map: Fix system add error after map page refresh
|
||||
|
||||
## [v1.12.0](https://github.com/wanderer-industries/wanderer/compare/v1.11.5...v1.12.0) (2024-10-16)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* Map: Prettify user settings
|
||||
|
||||
## [v1.11.5](https://github.com/wanderer-industries/wanderer/compare/v1.11.4...v1.11.5) (2024-10-16)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.11.4](https://github.com/wanderer-industries/wanderer/compare/v1.11.3...v1.11.4) (2024-10-16)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.11.3](https://github.com/wanderer-industries/wanderer/compare/v1.11.2...v1.11.3) (2024-10-16)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.11.2](https://github.com/wanderer-industries/wanderer/compare/v1.11.1...v1.11.2) (2024-10-15)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.11.1](https://github.com/wanderer-industries/wanderer/compare/v1.11.0...v1.11.1) (2024-10-14)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.11.0](https://github.com/wanderer-industries/wanderer/compare/v1.10.0...v1.11.0) (2024-10-14)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* Map: Add map level option to store custom labels
|
||||
|
||||
## [v1.10.0](https://github.com/wanderer-industries/wanderer/compare/v1.9.0...v1.10.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)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* Map: Follow Character on Map and auto select their current system
|
||||
|
||||
## [v1.3.6](https://github.com/wanderer-industries/wanderer/compare/v1.3.5...v1.3.6) (2024-10-09)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Signatures: Signatures update fixes
|
||||
|
||||
## [v1.3.0](https://github.com/wanderer-industries/wanderer/compare/v1.2.10...v1.3.0) (2024-10-07)
|
||||
|
||||
|
||||
@@ -20,26 +132,6 @@
|
||||
|
||||
* Map: Revision of sorting from also adding ability to sort all columns
|
||||
|
||||
## [v1.2.10](https://github.com/wanderer-industries/wanderer/compare/v1.2.9...v1.2.10) (2024-10-07)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.2.9](https://github.com/wanderer-industries/wanderer/compare/v1.2.8...v1.2.9) (2024-10-07)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.2.8](https://github.com/wanderer-industries/wanderer/compare/v1.2.7...v1.2.8) (2024-10-06)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.2.7](https://github.com/wanderer-industries/wanderer/compare/v1.2.6...v1.2.7) (2024-10-05)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.2.6](https://github.com/wanderer-industries/wanderer/compare/v1.2.5...v1.2.6) (2024-10-05)
|
||||
|
||||
|
||||
@@ -76,11 +168,6 @@
|
||||
|
||||
* Map: Fix map loading after select a different map.
|
||||
|
||||
## [v1.2.2](https://github.com/wanderer-industries/wanderer/compare/v1.2.1...v1.2.2) (2024-10-02)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.2.1](https://github.com/wanderer-industries/wanderer/compare/v1.2.0...v1.2.1) (2024-10-02)
|
||||
|
||||
|
||||
@@ -197,20 +284,10 @@
|
||||
|
||||
* docker: Fix DB connection in docker-compose internal network
|
||||
|
||||
## [v1.0.7](https://github.com/wanderer-industries/wanderer/compare/v1.0.6...v1.0.7) (2024-09-19)
|
||||
|
||||
## [v1.0.6](https://github.com/wanderer-industries/wanderer/compare/v1.0.5...v1.0.6) (2024-09-18)
|
||||
|
||||
## [v1.0.5](https://github.com/wanderer-industries/wanderer/compare/v1.0.4...v1.0.5) (2024-09-18)
|
||||
|
||||
## [v1.0.4](https://github.com/wanderer-industries/wanderer/compare/v1.0.3...v1.0.4) (2024-09-18)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* core: skip search results for failed character info request
|
||||
|
||||
## [v1.0.3](https://github.com/wanderer-industries/wanderer/compare/v1.0.2...v1.0.3) (2024-09-18)
|
||||
|
||||
## [v1.0.2](https://github.com/wanderer-industries/wanderer/compare/v1.0.1...v1.0.2) (2024-09-18)
|
||||
|
||||
## [v1.0.1](https://github.com/wanderer-industries/wanderer/compare/v1.0.0...v1.0.1) (2024-09-18)
|
||||
|
||||
@@ -28,6 +28,12 @@ body {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
#bg-canvas {
|
||||
position: absolute;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.ccp-font {
|
||||
font-family: 'Shentox', 'Rogan', sans-serif !important;
|
||||
}
|
||||
|
||||
@@ -85,3 +85,26 @@
|
||||
}
|
||||
}
|
||||
|
||||
.p-dropdown-label, .p-inputtext {
|
||||
padding: 0.25rem 0.75rem;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.p-dropdown-item {
|
||||
padding: 0.25rem 0.5rem;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.p-dropdown-item-group {
|
||||
padding: 0.25rem 0.75rem;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.p-dropdown-trigger {
|
||||
width: 14px;
|
||||
margin: 0 12px;
|
||||
}
|
||||
|
||||
.p-dropdown-empty-message {
|
||||
padding: 0.25rem 0.5rem;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Основной класс диалога */
|
||||
.p-dialog {
|
||||
body .p-dialog {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
//position: absolute;
|
||||
@@ -7,11 +7,26 @@
|
||||
left: 0;
|
||||
//visibility: hidden;
|
||||
overflow: hidden;
|
||||
border-radius: 6px;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 2px 10px 0 rgba(0,0,0,0.2);
|
||||
transition: box-shadow 0.3s;
|
||||
background: #fff;
|
||||
z-index: 1000;
|
||||
border: 1px solid #212121;
|
||||
background: var(--surface-h);
|
||||
color: var(--text-color);
|
||||
|
||||
.p-dialog-header {
|
||||
background: #171717 !important;
|
||||
color: var(--text-color);
|
||||
|
||||
.p-dialog-header-icon:focus-visible {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.p-dialog-footer {
|
||||
border-top: 1px solid var(--surface-d);
|
||||
}
|
||||
}
|
||||
|
||||
/* Стиль видимого диалога */
|
||||
@@ -45,12 +60,12 @@
|
||||
justify-content: space-between;
|
||||
padding: 1rem;
|
||||
background: #f4f4f4;
|
||||
border-bottom: 1px solid #ddd;
|
||||
//border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
/* Содержимое диалога */
|
||||
.p-dialog-content {
|
||||
padding: 1rem;
|
||||
padding: 0.5rem;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
}
|
||||
@@ -78,23 +93,3 @@
|
||||
.p-dialog-header-close .pi {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
/* Тема Saga Blue (пример) */
|
||||
body .p-dialog {
|
||||
background: var(--surface-a);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
body .p-dialog .p-dialog-header,
|
||||
body .p-dialog .p-dialog-footer {
|
||||
background: var(--surface-b);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
body .p-dialog .p-dialog-header {
|
||||
border-bottom: 1px solid var(--surface-d);
|
||||
}
|
||||
|
||||
body .p-dialog .p-dialog-footer {
|
||||
border-top: 1px solid var(--surface-d);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
--surface-d: #3f4b5b;
|
||||
--surface-e: #2a323d;
|
||||
--surface-f: #2a323d;
|
||||
--surface-h: #171717;
|
||||
--text-color: rgba(255, 255, 255, 0.87);
|
||||
--text-color-secondary: rgba(255, 255, 255, 0.6);
|
||||
--primary-color: #8dd0ff;
|
||||
|
||||
@@ -11,7 +11,7 @@ const Characters = ({ data }: { data: CharacterTypeRaw[] }) => {
|
||||
|
||||
const handleSelect = useCallback(
|
||||
(character: CharacterTypeRaw) => {
|
||||
mapRef.current?.command(Commands.selectSystem, character?.location?.solar_system_id?.toString());
|
||||
mapRef.current?.command(Commands.centerSystem, character?.location?.solar_system_id?.toString());
|
||||
},
|
||||
[mapRef],
|
||||
);
|
||||
|
||||
@@ -46,7 +46,7 @@ export const useLabelsMenu = (
|
||||
}
|
||||
|
||||
// const labels = getLabels(system.labels);
|
||||
const hasLabels = labels.list.length > 0;
|
||||
const hasLabels = labels?.list?.length > 0;
|
||||
const statusList = hasLabels ? LABELS_ORDER : LABELS_ORDER.slice(1);
|
||||
|
||||
return [
|
||||
|
||||
@@ -4,6 +4,7 @@ import { OutCommand, OutCommandHandler } from '@/hooks/Mapper/types/mapHandlers.
|
||||
import { SolarSystemRawType } from '@/hooks/Mapper/types';
|
||||
import { WaypointSetContextHandler } from '@/hooks/Mapper/components/contexts/types.ts';
|
||||
import { ctxManager } from '@/hooks/Mapper/utils/contextManager.ts';
|
||||
import { useDeleteSystems } from '@/hooks/Mapper/components/contexts/hooks';
|
||||
|
||||
interface UseContextMenuSystemHandlersProps {
|
||||
hubs: string[];
|
||||
@@ -16,8 +17,10 @@ export const useContextMenuSystemHandlers = ({ systems, hubs, outCommand }: UseC
|
||||
|
||||
const [system, setSystem] = useState<string>();
|
||||
|
||||
const ref = useRef({ hubs, system, systems, outCommand });
|
||||
ref.current = { hubs, system, systems, outCommand };
|
||||
const { deleteSystems } = useDeleteSystems();
|
||||
|
||||
const ref = useRef({ hubs, system, systems, outCommand, deleteSystems });
|
||||
ref.current = { hubs, system, systems, outCommand, deleteSystems };
|
||||
|
||||
const open = useCallback((ev: any, systemId: string) => {
|
||||
setSystem(systemId);
|
||||
@@ -27,12 +30,12 @@ export const useContextMenuSystemHandlers = ({ systems, hubs, outCommand }: UseC
|
||||
}, []);
|
||||
|
||||
const onDeleteSystem = useCallback(() => {
|
||||
const { system, outCommand } = ref.current;
|
||||
const { system, deleteSystems } = ref.current;
|
||||
if (!system) {
|
||||
return;
|
||||
}
|
||||
|
||||
outCommand({ type: OutCommand.deleteSystems, data: [system] });
|
||||
deleteSystems([system]);
|
||||
setSystem(undefined);
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { getSystemById } from '@/hooks/Mapper/helpers';
|
||||
import { useWaypointMenu } from '@/hooks/Mapper/components/contexts/hooks';
|
||||
import { WaypointSetContextHandler } from '@/hooks/Mapper/components/contexts/types.ts';
|
||||
import { FastSystemActions } from '@/hooks/Mapper/components/contexts/components';
|
||||
import { useJumpPlannerMenu } from '@/hooks/Mapper/components/contexts/hooks/useJumpPlannerMenu';
|
||||
import { useJumpPlannerMenu } from '@/hooks/Mapper/components/contexts/hooks';
|
||||
import { Route } from '@/hooks/Mapper/types/routes.ts';
|
||||
|
||||
export interface ContextMenuSystemInfoProps {
|
||||
|
||||
@@ -48,19 +48,19 @@ export const useContextMenuSystemInfoHandlers = ({ hubs, outCommand, mapRef }: U
|
||||
}, []);
|
||||
|
||||
const onAddSystem = useCallback(() => {
|
||||
const { system, outCommand, mapRef } = ref.current;
|
||||
if (!system) {
|
||||
const { system: solarSystemId, outCommand, mapRef } = ref.current;
|
||||
if (!solarSystemId) {
|
||||
return;
|
||||
}
|
||||
|
||||
outCommand({
|
||||
type: OutCommand.addSystem,
|
||||
data: {
|
||||
system_id: system,
|
||||
system_id: solarSystemId,
|
||||
},
|
||||
});
|
||||
setTimeout(() => {
|
||||
mapRef.current?.command(Commands.selectSystem, system);
|
||||
mapRef.current?.command(Commands.centerSystem, solarSystemId);
|
||||
setSystem(undefined);
|
||||
}, 200);
|
||||
}, []);
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { Node } from 'reactflow';
|
||||
import { useRef, useState } from 'react';
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
import { ContextMenu } from 'primereact/contextmenu';
|
||||
import { OutCommand } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { SolarSystemRawType } from '@/hooks/Mapper/types';
|
||||
import { ctxManager } from '@/hooks/Mapper/utils/contextManager.ts';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { NodeSelectionMouseHandler } from '@/hooks/Mapper/components/contexts/types.ts';
|
||||
import { useDeleteSystems } from '@/hooks/Mapper/components/contexts/hooks';
|
||||
|
||||
export const useContextMenuSystemMultipleHandlers = () => {
|
||||
const contextMenuRef = useRef<ContextMenu | null>(null);
|
||||
const { outCommand } = useMapRootState();
|
||||
const [systems, setSystems] = useState<Node<SolarSystemRawType>[]>();
|
||||
|
||||
const { deleteSystems } = useDeleteSystems();
|
||||
|
||||
const handleSystemMultipleContext: NodeSelectionMouseHandler = (ev, systems_) => {
|
||||
setSystems(systems_);
|
||||
ev.preventDefault();
|
||||
@@ -19,7 +19,7 @@ export const useContextMenuSystemMultipleHandlers = () => {
|
||||
contextMenuRef.current?.show(ev);
|
||||
};
|
||||
|
||||
const onDeleteSystems = () => {
|
||||
const onDeleteSystems = useCallback(() => {
|
||||
if (!systems) {
|
||||
return;
|
||||
}
|
||||
@@ -29,12 +29,11 @@ export const useContextMenuSystemMultipleHandlers = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
outCommand({ type: OutCommand.deleteSystems, data: sysToDel });
|
||||
};
|
||||
deleteSystems(sysToDel);
|
||||
}, [deleteSystems, systems]);
|
||||
|
||||
return {
|
||||
handleSystemMultipleContext,
|
||||
|
||||
contextMenuRef,
|
||||
onDeleteSystems,
|
||||
};
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export * from './useWaypointMenu';
|
||||
export * from './useJumpPlannerMenu';
|
||||
export * from './useDeleteSystems';
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { OutCommand } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
|
||||
export const useDeleteSystems = () => {
|
||||
const { outCommand } = useMapRootState();
|
||||
|
||||
const deleteSystems = (systemIds: string[]) => {
|
||||
if (!systemIds || !systemIds.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
outCommand({ type: OutCommand.deleteSystems, data: systemIds });
|
||||
};
|
||||
|
||||
return {
|
||||
deleteSystems,
|
||||
};
|
||||
};
|
||||
2
assets/js/hooks/Mapper/components/hooks/index.ts
Normal file
2
assets/js/hooks/Mapper/components/hooks/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './useSystemInfo';
|
||||
export * from './useGetOwnOnlineCharacters';
|
||||
33
assets/js/hooks/Mapper/components/hooks/useSystemInfo.ts
Normal file
33
assets/js/hooks/Mapper/components/hooks/useSystemInfo.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { useMemo } from 'react';
|
||||
import { getSystemById } from '@/hooks/Mapper/helpers';
|
||||
import { useLoadSystemStatic } from '@/hooks/Mapper/mapRootProvider/hooks/useLoadSystemStatic.ts';
|
||||
|
||||
interface UseSystemInfoProps {
|
||||
systemId: string;
|
||||
}
|
||||
|
||||
export const useSystemInfo = ({ systemId }: UseSystemInfoProps) => {
|
||||
const {
|
||||
data: { systems, connections },
|
||||
} = useMapRootState();
|
||||
|
||||
const { systems: systemStatics } = useLoadSystemStatic({ systems: [systemId] });
|
||||
|
||||
return useMemo(() => {
|
||||
const staticInfo = systemStatics.get(parseInt(systemId));
|
||||
const dynamicInfo = getSystemById(systems, systemId);
|
||||
|
||||
if (!staticInfo || !dynamicInfo) {
|
||||
throw new Error(`Error on getting system ${systemId}`);
|
||||
}
|
||||
|
||||
const leadsTo = connections
|
||||
.filter(x => [x.source, x.target].includes(systemId))
|
||||
.map(x => [x.source, x.target])
|
||||
.flat()
|
||||
.filter(x => x !== systemId);
|
||||
|
||||
return { dynamicInfo, staticInfo, leadsTo };
|
||||
}, [systemStatics, systemId, systems, connections]);
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ForwardedRef, forwardRef, MouseEvent, useCallback, useEffect } from 'react';
|
||||
import { ForwardedRef, forwardRef, MouseEvent, useCallback, useEffect, useRef } from 'react';
|
||||
import ReactFlow, {
|
||||
Background,
|
||||
ConnectionMode,
|
||||
@@ -13,12 +13,15 @@ import ReactFlow, {
|
||||
SelectionMode,
|
||||
useEdgesState,
|
||||
useNodesState,
|
||||
NodeChange,
|
||||
useReactFlow,
|
||||
} from 'reactflow';
|
||||
import 'reactflow/dist/style.css';
|
||||
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 {
|
||||
@@ -34,6 +37,7 @@ 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 };
|
||||
|
||||
@@ -108,6 +112,7 @@ const MapComp = ({
|
||||
isShowMinimap,
|
||||
showKSpaceBG,
|
||||
}: MapCompProps) => {
|
||||
const { getNode } = useReactFlow();
|
||||
const [nodes, , onNodesChange] = useNodesState<SolarSystemRawType>(initialNodes);
|
||||
const [edges, , onEdgesChange] = useEdgesState<Edge<SolarSystemConnection>[]>(initialEdges);
|
||||
|
||||
@@ -115,8 +120,15 @@ const MapComp = ({
|
||||
useUpdateNodes(nodes);
|
||||
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 => {
|
||||
@@ -171,6 +183,32 @@ const MapComp = ({
|
||||
localStorage.setItem(SESSION_KEY.viewPort, JSON.stringify(viewport));
|
||||
};
|
||||
|
||||
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 {
|
||||
systemsIdsToRemove.push(node?.data?.id);
|
||||
}
|
||||
return acc;
|
||||
}
|
||||
return [...acc, change];
|
||||
}, [] as NodeChange[]);
|
||||
|
||||
if (systemsIdsToRemove.length) {
|
||||
deleteSystems(systemsIdsToRemove);
|
||||
}
|
||||
|
||||
onNodesChange(nextChanges);
|
||||
},
|
||||
[deleteSystems, getNode, onNodesChange],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
update(x => ({
|
||||
...x,
|
||||
@@ -184,7 +222,7 @@ const MapComp = ({
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
onNodesChange={onNodesChange}
|
||||
onNodesChange={handleNodesChange}
|
||||
onEdgesChange={onEdgesChange}
|
||||
onConnect={onConnect}
|
||||
// TODO we need save into session all of this
|
||||
@@ -219,10 +257,10 @@ const MapComp = ({
|
||||
minZoom={0.2}
|
||||
maxZoom={1.5}
|
||||
elevateNodesOnSelect
|
||||
deleteKeyCode={['Delete']}
|
||||
// TODO need create clear example with problem with that flag
|
||||
// if system is not visible edge not drawing (and any render in Custom node is not happening)
|
||||
// onlyRenderVisibleElements
|
||||
deleteKeyCode={null}
|
||||
selectionMode={SelectionMode.Partial}
|
||||
>
|
||||
{isShowMinimap && <MiniMap pannable zoomable ariaLabel="Mini map" className={minimapClasses} />}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "@/hooks/Mapper/components/map/styles/eve-common-variables";
|
||||
@import '@/hooks/Mapper/components/map/styles/eve-common-variables';
|
||||
|
||||
$pastel-blue: #5a7d9a;
|
||||
$pastel-pink: #d291bc;
|
||||
@@ -25,9 +25,11 @@ $tooltip-bg: #202020; // Темный фон для подсказок
|
||||
z-index: 1;
|
||||
overflow: hidden;
|
||||
|
||||
|
||||
&.Mataria, &.Amarria, &.Gallente, &.Caldaria {
|
||||
&::Before {
|
||||
&.Mataria,
|
||||
&.Amarria,
|
||||
&.Gallente,
|
||||
&.Caldaria {
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -44,42 +46,40 @@ $tooltip-bg: #202020; // Темный фон для подсказок
|
||||
|
||||
&.Mataria {
|
||||
&::before {
|
||||
background-image: url("/images/mataria.png");
|
||||
background-image: url('/images/mataria-180.png');
|
||||
opacity: 0.6;
|
||||
background-position-x: -28px;
|
||||
background-position-y: -3px;
|
||||
background-position-x: 1px;
|
||||
background-position-y: -14px;
|
||||
}
|
||||
}
|
||||
|
||||
&.Caldaria {
|
||||
&::before {
|
||||
background-image: url("/images/caldaria.png");
|
||||
background-image: url('/images/caldaria-180.png');
|
||||
opacity: 0.6;
|
||||
background-position-x: -16px;
|
||||
background-position-y: -17px;
|
||||
background-position-x: 1px;
|
||||
background-position-y: -10px;
|
||||
}
|
||||
}
|
||||
|
||||
&.Amarria {
|
||||
&::before {
|
||||
opacity: 0.45;
|
||||
background-image: url("/images/amarr.png");
|
||||
background-position-x: 0px;
|
||||
background-position-y: -1px;
|
||||
width: calc(100% + 10px)
|
||||
background-image: url('/images/amarr-180.png');
|
||||
background-position-x: 0;
|
||||
background-position-y: -13px;
|
||||
}
|
||||
}
|
||||
|
||||
&.Gallente {
|
||||
&::before {
|
||||
opacity: 0.6;
|
||||
background-image: url("/images/gallente.png");
|
||||
background-position-x: -1px;
|
||||
background-position-y: -10px;
|
||||
opacity: 0.5;
|
||||
background-image: url('/images/gallente-180.png');
|
||||
background-position-x: 1px;
|
||||
background-position-y: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&.selected {
|
||||
border-color: $pastel-pink;
|
||||
box-shadow: 0 0 10px #9a1af1c2;
|
||||
@@ -95,7 +95,7 @@ $tooltip-bg: #202020; // Темный фон для подсказок
|
||||
|
||||
&.eve-system-status-home {
|
||||
border: 1px solid darken($eve-solar-system-status-color-home, 30%);
|
||||
background-image: linear-gradient(45deg, $eve-solar-system-status-friendly, transparent);
|
||||
background-image: linear-gradient(275deg, $eve-solar-system-status-friendly, transparent);
|
||||
|
||||
&.selected {
|
||||
border-color: $eve-solar-system-status-color-home;
|
||||
@@ -104,7 +104,7 @@ $tooltip-bg: #202020; // Темный фон для подсказок
|
||||
|
||||
&.eve-system-status-friendly {
|
||||
border: 1px solid darken($eve-solar-system-status-color-friendly, 20%);
|
||||
background-image: linear-gradient(45deg, darken($eve-solar-system-status-friendly, 30%), transparent);
|
||||
background-image: linear-gradient(275deg, darken($eve-solar-system-status-friendly, 30%), transparent);
|
||||
|
||||
&.selected {
|
||||
border-color: darken($eve-solar-system-status-color-friendly, 5%);
|
||||
@@ -113,7 +113,7 @@ $tooltip-bg: #202020; // Темный фон для подсказок
|
||||
|
||||
&.eve-system-status-lookingFor {
|
||||
border: 1px solid darken($eve-solar-system-status-color-lookingFor, 15%);
|
||||
background-image: linear-gradient(45deg, #45ff8f2f, #457fff2f);
|
||||
background-image: linear-gradient(275deg, #45ff8f2f, #457fff2f);
|
||||
|
||||
&.selected {
|
||||
border-color: $pastel-pink;
|
||||
@@ -121,17 +121,16 @@ $tooltip-bg: #202020; // Темный фон для подсказок
|
||||
}
|
||||
|
||||
&.eve-system-status-warning {
|
||||
background-image: linear-gradient(45deg, $eve-solar-system-status-warning, transparent);
|
||||
background-image: linear-gradient(275deg, $eve-solar-system-status-warning, transparent);
|
||||
}
|
||||
|
||||
&.eve-system-status-dangerous {
|
||||
background-image: linear-gradient(45deg, $eve-solar-system-status-dangerous, transparent);
|
||||
background-image: linear-gradient(275deg, $eve-solar-system-status-dangerous, transparent);
|
||||
}
|
||||
|
||||
&.eve-system-status-target {
|
||||
background-image: linear-gradient(45deg, $eve-solar-system-status-target, transparent);
|
||||
background-image: linear-gradient(275deg, $eve-solar-system-status-target, transparent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.Bookmarks {
|
||||
@@ -158,7 +157,7 @@ $tooltip-bg: #202020; // Темный фон для подсказок
|
||||
//background-color: #833ca4;
|
||||
|
||||
&:not(:first-child) {
|
||||
box-shadow: inset 4px -3px 4px rgba(0, 0, 0, .3);
|
||||
box-shadow: inset 4px -3px 4px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +180,6 @@ $tooltip-bg: #202020; // Темный фон для подсказок
|
||||
font-size: 9px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.icon {
|
||||
@@ -219,9 +217,7 @@ $tooltip-bg: #202020; // Темный фон для подсказок
|
||||
}
|
||||
|
||||
.solarSystemName {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.BottomRow {
|
||||
@@ -288,11 +284,19 @@ $tooltip-bg: #202020; // Темный фон для подсказок
|
||||
border-color: $pastel-pink;
|
||||
}
|
||||
|
||||
&.HandleTop { top: -2px }
|
||||
&.HandleTop {
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
&.HandleRight { right: -2px }
|
||||
&.HandleRight {
|
||||
right: -2px;
|
||||
}
|
||||
|
||||
&.HandleBottom { bottom: -2px }
|
||||
&.HandleBottom {
|
||||
bottom: -2px;
|
||||
}
|
||||
|
||||
&.HandleLeft { left: -2px }
|
||||
&.HandleLeft {
|
||||
left: -2px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ const SpaceToClass: Record<string, string> = {
|
||||
};
|
||||
|
||||
const sortedLabels = (labels: string[]) => {
|
||||
if (labels === null) {
|
||||
if (!labels) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ export const SolarSystemNode = memo(({ data, selected }: WrapNodeProps<MapSolarS
|
||||
<div className={classes.Bookmarks}>
|
||||
{labelCustom !== '' && (
|
||||
<div className={clsx(classes.Bookmark, MARKER_BOOKMARK_BG_STYLES.custom)}>
|
||||
<div>{labelCustom}</div>
|
||||
<span className="[text-shadow:_0_1px_0_rgb(0_0_0_/_40%)] ">{labelCustom}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -168,14 +168,16 @@ export const SolarSystemNode = memo(({ data, selected }: WrapNodeProps<MapSolarS
|
||||
{visible && (
|
||||
<>
|
||||
<div className={classes.HeadRow}>
|
||||
<div className={clsx(classes.classTitle, classTitleColor)}>{class_title ?? '-'}</div>
|
||||
<div className={clsx(classes.classTitle, classTitleColor, '[text-shadow:_0_1px_0_rgb(0_0_0_/_40%)]')}>
|
||||
{class_title ?? '-'}
|
||||
</div>
|
||||
{tag != null && tag !== '' && (
|
||||
<div className={clsx(classes.TagTitle, 'text-sky-400 font-medium')}>{tag}</div>
|
||||
)}
|
||||
<div
|
||||
className={clsx(
|
||||
classes.classSystemName,
|
||||
'flex-grow overflow-hidden text-ellipsis whitespace-nowrap font-sans',
|
||||
'[text-shadow:_0_1px_0_rgb(0_0_0_/_40%)] flex-grow overflow-hidden text-ellipsis whitespace-nowrap font-sans',
|
||||
)}
|
||||
>
|
||||
{solar_system_name}
|
||||
@@ -196,16 +198,16 @@ export const SolarSystemNode = memo(({ data, selected }: WrapNodeProps<MapSolarS
|
||||
|
||||
<div className={clsx(classes.BottomRow, 'flex items-center justify-between')}>
|
||||
{customName && (
|
||||
<div className="text-blue-300 whitespace-nowrap overflow-hidden text-ellipsis mr-0.5">{customName}</div>
|
||||
<div className="[text-shadow:_0_1px_0_rgb(0_0_0_/_40%)] text-blue-300 whitespace-nowrap overflow-hidden text-ellipsis mr-0.5">
|
||||
{customName}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!isWormhole && !customName && (
|
||||
<div
|
||||
className={clsx('text-stone-400 whitespace-nowrap overflow-hidden text-ellipsis mr-0.5', {
|
||||
['text-teal-100 font-bold']: space === Spaces.Caldari,
|
||||
['text-yellow-100 font-bold']: space === Spaces.Amarr || space === Spaces.Matar,
|
||||
['text-lime-200/80 font-bold']: space === Spaces.Gallente,
|
||||
})}
|
||||
className={clsx(
|
||||
'[text-shadow:_0_1px_0_rgb(0_0_0_/_40%)] text-stone-300 whitespace-nowrap overflow-hidden text-ellipsis mr-0.5',
|
||||
)}
|
||||
>
|
||||
{region_name}
|
||||
</div>
|
||||
@@ -215,10 +217,10 @@ export const SolarSystemNode = memo(({ data, selected }: WrapNodeProps<MapSolarS
|
||||
|
||||
<div className="flex items-center justify-end">
|
||||
<div className="flex gap-1 items-center">
|
||||
{locked && <i className={PrimeIcons.LOCK} style={{ fontSize: '0.45rem' }}></i>}
|
||||
{locked && <i className={PrimeIcons.LOCK} style={{ fontSize: '0.45rem', fontWeight: 'bold' }}></i>}
|
||||
|
||||
{hubs.includes(solar_system_id.toString()) && (
|
||||
<i className={PrimeIcons.MAP_MARKER} style={{ fontSize: '0.45rem' }}></i>
|
||||
<i className={PrimeIcons.MAP_MARKER} style={{ fontSize: '0.45rem', fontWeight: 'bold' }}></i>
|
||||
)}
|
||||
|
||||
{charactersInSystem.length > 0 && (
|
||||
|
||||
@@ -18,5 +18,9 @@ export const WormholeClassComp = ({ id }: WormholeClassComp) => {
|
||||
}
|
||||
|
||||
const colorClass = WORMHOLE_CLASS_STYLES[wormholeDataAdditional.wormholeClassID.toString()];
|
||||
return <div className={clsx(colorClass)}>{wormholeDataAdditional.shortName}</div>;
|
||||
return (
|
||||
<div className={clsx(colorClass, '[text-shadow:_0_1px_0_rgb(0_0_0_/_40%)]')}>
|
||||
{wormholeDataAdditional.shortName}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -30,11 +30,77 @@ export enum SOLAR_SYSTEM_CLASS_IDS {
|
||||
zarzakh = 10100,
|
||||
}
|
||||
|
||||
export enum SOLAR_SYSTEM_CLASS_GROUPS {
|
||||
ccp = 'ccp',
|
||||
c1 = 'c1',
|
||||
c2 = 'c2',
|
||||
c3 = 'c3',
|
||||
c4 = 'c4',
|
||||
c5 = 'c5',
|
||||
c6 = 'c6',
|
||||
hs = 'hs',
|
||||
ls = 'ls',
|
||||
ns = 'ns',
|
||||
thera = 'thera',
|
||||
c13 = 'c13',
|
||||
drifter = 'drifter',
|
||||
unknown = 'unknown',
|
||||
pochven = 'pochven',
|
||||
jovian = 'jovian',
|
||||
}
|
||||
|
||||
export const SOLAR_SYSTEM_TO_CLASS_GROUPS_CLASSES = {
|
||||
c1: ['c1'],
|
||||
c2: ['c2'],
|
||||
c3: ['c3'],
|
||||
c4: ['c4'],
|
||||
c5: ['c5'],
|
||||
c6: ['c6'],
|
||||
hs: ['hs'],
|
||||
ls: ['ls'],
|
||||
ns: ['ns'],
|
||||
thera: ['thera'],
|
||||
c13: ['c13'],
|
||||
pochven: ['pochven'],
|
||||
drifter: ['sentinel', 'barbican', 'vidette', 'conflux', 'redoubt'],
|
||||
jove: ['jove'],
|
||||
};
|
||||
|
||||
export const SOLAR_SYSTEM_CLASSES_TO_CLASS_GROUPS = {
|
||||
ccp1: SOLAR_SYSTEM_CLASS_GROUPS.ccp,
|
||||
c1: SOLAR_SYSTEM_CLASS_GROUPS.c1,
|
||||
c2: SOLAR_SYSTEM_CLASS_GROUPS.c2,
|
||||
c3: SOLAR_SYSTEM_CLASS_GROUPS.c3,
|
||||
c4: SOLAR_SYSTEM_CLASS_GROUPS.c4,
|
||||
c5: SOLAR_SYSTEM_CLASS_GROUPS.c5,
|
||||
c6: SOLAR_SYSTEM_CLASS_GROUPS.c6,
|
||||
hs: SOLAR_SYSTEM_CLASS_GROUPS.hs,
|
||||
ls: SOLAR_SYSTEM_CLASS_GROUPS.ls,
|
||||
ns: SOLAR_SYSTEM_CLASS_GROUPS.ns,
|
||||
ccp2: SOLAR_SYSTEM_CLASS_GROUPS.ccp,
|
||||
ccp3: SOLAR_SYSTEM_CLASS_GROUPS.ccp,
|
||||
thera: SOLAR_SYSTEM_CLASS_GROUPS.thera,
|
||||
c13: SOLAR_SYSTEM_CLASS_GROUPS.c13,
|
||||
sentinel: SOLAR_SYSTEM_CLASS_GROUPS.drifter,
|
||||
baribican: SOLAR_SYSTEM_CLASS_GROUPS.drifter,
|
||||
vidette: SOLAR_SYSTEM_CLASS_GROUPS.drifter,
|
||||
conflux: SOLAR_SYSTEM_CLASS_GROUPS.drifter,
|
||||
redoubt: SOLAR_SYSTEM_CLASS_GROUPS.drifter,
|
||||
a1: SOLAR_SYSTEM_CLASS_GROUPS.unknown,
|
||||
a2: SOLAR_SYSTEM_CLASS_GROUPS.unknown,
|
||||
a3: SOLAR_SYSTEM_CLASS_GROUPS.unknown,
|
||||
a4: SOLAR_SYSTEM_CLASS_GROUPS.unknown,
|
||||
a5: SOLAR_SYSTEM_CLASS_GROUPS.unknown,
|
||||
ccp4: SOLAR_SYSTEM_CLASS_GROUPS.ccp,
|
||||
pochven: SOLAR_SYSTEM_CLASS_GROUPS.pochven,
|
||||
};
|
||||
|
||||
type WormholesAdditionalInfoType = {
|
||||
id: string;
|
||||
shortName: string;
|
||||
wormholeClassID: number;
|
||||
title: string;
|
||||
shortTitle: string;
|
||||
effectPower?: number;
|
||||
};
|
||||
|
||||
@@ -45,6 +111,7 @@ export const WORMHOLES_ADDITIONAL_INFO_RAW: WormholesAdditionalInfoType[] = [
|
||||
shortName: 'CCP',
|
||||
wormholeClassID: -1,
|
||||
title: 'CCP System',
|
||||
shortTitle: 'CCP',
|
||||
},
|
||||
{
|
||||
id: 'c1',
|
||||
@@ -52,6 +119,7 @@ export const WORMHOLES_ADDITIONAL_INFO_RAW: WormholesAdditionalInfoType[] = [
|
||||
wormholeClassID: 1,
|
||||
effectPower: 1,
|
||||
title: 'Class 1',
|
||||
shortTitle: 'C1',
|
||||
},
|
||||
{
|
||||
id: 'c2',
|
||||
@@ -59,6 +127,7 @@ export const WORMHOLES_ADDITIONAL_INFO_RAW: WormholesAdditionalInfoType[] = [
|
||||
wormholeClassID: 2,
|
||||
effectPower: 2,
|
||||
title: 'Class 2',
|
||||
shortTitle: 'C2',
|
||||
},
|
||||
{
|
||||
id: 'c3',
|
||||
@@ -66,6 +135,7 @@ export const WORMHOLES_ADDITIONAL_INFO_RAW: WormholesAdditionalInfoType[] = [
|
||||
wormholeClassID: 3,
|
||||
effectPower: 3,
|
||||
title: 'Class 3',
|
||||
shortTitle: 'C3',
|
||||
},
|
||||
{
|
||||
id: 'c4',
|
||||
@@ -73,6 +143,7 @@ export const WORMHOLES_ADDITIONAL_INFO_RAW: WormholesAdditionalInfoType[] = [
|
||||
wormholeClassID: 4,
|
||||
effectPower: 4,
|
||||
title: 'Class 4',
|
||||
shortTitle: 'C4',
|
||||
},
|
||||
{
|
||||
id: 'c5',
|
||||
@@ -80,6 +151,7 @@ export const WORMHOLES_ADDITIONAL_INFO_RAW: WormholesAdditionalInfoType[] = [
|
||||
wormholeClassID: 5,
|
||||
effectPower: 5,
|
||||
title: 'Class 5',
|
||||
shortTitle: 'C5',
|
||||
},
|
||||
{
|
||||
id: 'c6',
|
||||
@@ -87,42 +159,49 @@ export const WORMHOLES_ADDITIONAL_INFO_RAW: WormholesAdditionalInfoType[] = [
|
||||
wormholeClassID: 6,
|
||||
effectPower: 6,
|
||||
title: 'Class 6',
|
||||
shortTitle: 'C6',
|
||||
},
|
||||
{
|
||||
id: 'hs',
|
||||
shortName: 'H',
|
||||
wormholeClassID: 7,
|
||||
title: 'High-sec',
|
||||
shortTitle: 'High-sec',
|
||||
},
|
||||
{
|
||||
id: 'ls',
|
||||
shortName: 'L',
|
||||
wormholeClassID: 8,
|
||||
title: 'Low-sec',
|
||||
shortTitle: 'Low-sec',
|
||||
},
|
||||
{
|
||||
id: 'ns',
|
||||
shortName: 'N',
|
||||
wormholeClassID: 9,
|
||||
title: 'Null-sec',
|
||||
shortTitle: 'Null-sec',
|
||||
},
|
||||
{
|
||||
id: 'ccp2',
|
||||
shortName: 'CCP',
|
||||
wormholeClassID: 10,
|
||||
title: 'CCP System',
|
||||
shortTitle: 'CCP',
|
||||
},
|
||||
{
|
||||
id: 'ccp3',
|
||||
shortName: 'CCP',
|
||||
wormholeClassID: 11,
|
||||
title: 'CCP System',
|
||||
shortTitle: 'CCP',
|
||||
},
|
||||
{
|
||||
id: 'thera',
|
||||
shortName: 'T',
|
||||
wormholeClassID: 12,
|
||||
title: 'Class 12 (Thera)',
|
||||
shortTitle: 'Thera',
|
||||
},
|
||||
{
|
||||
id: 'c13',
|
||||
@@ -130,6 +209,7 @@ export const WORMHOLES_ADDITIONAL_INFO_RAW: WormholesAdditionalInfoType[] = [
|
||||
wormholeClassID: 13,
|
||||
effectPower: 6,
|
||||
title: 'Class 13 (Shattered Frigate)',
|
||||
shortTitle: 'C13',
|
||||
},
|
||||
{
|
||||
id: 'sentinel',
|
||||
@@ -137,6 +217,7 @@ export const WORMHOLES_ADDITIONAL_INFO_RAW: WormholesAdditionalInfoType[] = [
|
||||
wormholeClassID: 14,
|
||||
effectPower: 2,
|
||||
title: 'Class 14 (Sentinel Drifter)',
|
||||
shortTitle: 'Sentinel',
|
||||
},
|
||||
{
|
||||
id: 'barbican',
|
||||
@@ -144,6 +225,7 @@ export const WORMHOLES_ADDITIONAL_INFO_RAW: WormholesAdditionalInfoType[] = [
|
||||
wormholeClassID: 15,
|
||||
effectPower: 2,
|
||||
title: 'Class 15 (Barbican Drifter)',
|
||||
shortTitle: 'Barbican',
|
||||
},
|
||||
{
|
||||
id: 'vidette',
|
||||
@@ -151,6 +233,7 @@ export const WORMHOLES_ADDITIONAL_INFO_RAW: WormholesAdditionalInfoType[] = [
|
||||
wormholeClassID: 16,
|
||||
effectPower: 2,
|
||||
title: 'Class 16 (Vidette Drifter)',
|
||||
shortTitle: 'Vidette',
|
||||
},
|
||||
{
|
||||
id: 'conflux',
|
||||
@@ -158,6 +241,7 @@ export const WORMHOLES_ADDITIONAL_INFO_RAW: WormholesAdditionalInfoType[] = [
|
||||
wormholeClassID: 17,
|
||||
effectPower: 2,
|
||||
title: 'Class 17 (Conflux Drifter)',
|
||||
shortTitle: 'Conflux',
|
||||
},
|
||||
{
|
||||
id: 'redoubt',
|
||||
@@ -165,59 +249,79 @@ export const WORMHOLES_ADDITIONAL_INFO_RAW: WormholesAdditionalInfoType[] = [
|
||||
wormholeClassID: 18,
|
||||
effectPower: 2,
|
||||
title: 'Class 18 (Redoubt Drifter)',
|
||||
shortTitle: 'Redoubt',
|
||||
},
|
||||
{
|
||||
id: 'a1',
|
||||
shortName: 'A1',
|
||||
wormholeClassID: 19,
|
||||
title: '(Abyssal class 1)',
|
||||
shortTitle: 'A1',
|
||||
},
|
||||
{
|
||||
id: 'a2',
|
||||
shortName: 'A2',
|
||||
wormholeClassID: 20,
|
||||
title: '(Abyssal class 2)',
|
||||
shortTitle: 'A2',
|
||||
},
|
||||
{
|
||||
id: 'a3',
|
||||
shortName: 'A3',
|
||||
wormholeClassID: 21,
|
||||
title: '(Abyssal class 3)',
|
||||
shortTitle: 'A3',
|
||||
},
|
||||
{
|
||||
id: 'a4',
|
||||
shortName: 'A4',
|
||||
wormholeClassID: 22,
|
||||
title: '(Abyssal class 4)',
|
||||
shortTitle: 'A4',
|
||||
},
|
||||
{
|
||||
id: 'a5',
|
||||
shortName: 'A5',
|
||||
wormholeClassID: 23,
|
||||
title: '(Abyssal class 5)',
|
||||
shortTitle: 'A5',
|
||||
},
|
||||
{
|
||||
id: 'ccp4',
|
||||
shortName: 'CCP',
|
||||
wormholeClassID: 24,
|
||||
title: 'CCP System (Penalty)',
|
||||
shortTitle: 'CCP',
|
||||
},
|
||||
{
|
||||
id: 'pochven',
|
||||
shortName: 'P',
|
||||
wormholeClassID: 25,
|
||||
title: 'Triglavian space (Pochven)',
|
||||
shortTitle: 'Pochven',
|
||||
},
|
||||
{
|
||||
id: 'zarzakh',
|
||||
shortName: 'N',
|
||||
wormholeClassID: 10100,
|
||||
title: 'Pirate space',
|
||||
shortTitle: 'Zarzakh',
|
||||
},
|
||||
{
|
||||
id: 'k162',
|
||||
shortName: 'K162',
|
||||
wormholeClassID: 10101,
|
||||
title: 'Reverse',
|
||||
shortTitle: 'K162',
|
||||
},
|
||||
];
|
||||
|
||||
export const WORMHOLES_ADDITIONAL_INFO: Record<string, WormholesAdditionalInfoType> =
|
||||
WORMHOLES_ADDITIONAL_INFO_RAW.reduce((acc, x) => ({ ...acc, [x.id]: x }), {});
|
||||
|
||||
export const WORMHOLES_ADDITIONAL_INFO_BY_CLASS_ID: Record<string, WormholesAdditionalInfoType> =
|
||||
WORMHOLES_ADDITIONAL_INFO_RAW.reduce((acc, x) => ({ ...acc, [x.wormholeClassID]: x }), {});
|
||||
|
||||
// export const SOLAR_SYSTEM_CLASS_NAMES = {
|
||||
// ccp1 = ,
|
||||
// c1 = ,
|
||||
|
||||
@@ -5,5 +5,6 @@ export * from './useMapRemoveSystems';
|
||||
export * from './useCommandsCharacters';
|
||||
export * from './useCommandsConnections';
|
||||
export * from './useCommandsConnections';
|
||||
export * from './useCenterSystem';
|
||||
export * from './useSelectSystem';
|
||||
export * from './useMapCommands';
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { useReactFlow } from 'reactflow';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { CommandCenterSystem } from '@/hooks/Mapper/types';
|
||||
|
||||
export const useCenterSystem = () => {
|
||||
const rf = useReactFlow();
|
||||
|
||||
const ref = useRef({ rf });
|
||||
ref.current = { rf };
|
||||
|
||||
return useCallback((systemId: CommandCenterSystem) => {
|
||||
const systemNode = ref.current.rf.getNodes().find(x => x.data.id === systemId);
|
||||
if (!systemNode) {
|
||||
return;
|
||||
}
|
||||
ref.current.rf.setCenter(systemNode.position.x, systemNode.position.y, { duration: 1000 });
|
||||
}, []);
|
||||
};
|
||||
@@ -2,27 +2,22 @@ import { Node, useReactFlow } from 'reactflow';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { CommandAddSystems } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { convertSystem2Node } from '../../helpers';
|
||||
import { useMapState } from '@/hooks/Mapper/components/map/MapProvider.tsx';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
|
||||
export const useMapAddSystems = () => {
|
||||
const rf = useReactFlow();
|
||||
const {
|
||||
data: { systems },
|
||||
update,
|
||||
} = useMapState();
|
||||
} = useMapRootState();
|
||||
|
||||
const ref = useRef({ rf, systems, update });
|
||||
ref.current = { update, systems, rf };
|
||||
const ref = useRef({ rf, systems });
|
||||
ref.current = { systems, rf };
|
||||
|
||||
return useCallback(
|
||||
(systems: CommandAddSystems) => {
|
||||
const nodes = rf.getNodes();
|
||||
const prepared: Node[] = systems.filter(x => !nodes.some(y => x.id === y.id)).map(convertSystem2Node);
|
||||
rf.addNodes(prepared);
|
||||
|
||||
ref.current.update({
|
||||
systems: [...ref.current.systems.filter(sys => systems.some(x => sys.id !== x.id)), ...systems],
|
||||
});
|
||||
},
|
||||
[rf],
|
||||
);
|
||||
|
||||
@@ -4,18 +4,18 @@ import { CommandSelectSystem } from '@/hooks/Mapper/types';
|
||||
|
||||
export const useSelectSystem = () => {
|
||||
const rf = useReactFlow();
|
||||
|
||||
const ref = useRef({ rf });
|
||||
ref.current = { rf };
|
||||
|
||||
return useCallback((systemId: CommandSelectSystem) => {
|
||||
if (!ref.current?.rf) {
|
||||
return;
|
||||
}
|
||||
const systemNode = ref.current.rf.getNodes().find(x => x.data.id === systemId);
|
||||
if (!systemNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
ref.current.rf.setCenter(systemNode.position.x, systemNode.position.y, { duration: 1000 });
|
||||
ref.current.rf.setNodes(nds =>
|
||||
nds.map(node => {
|
||||
return {
|
||||
...node,
|
||||
selected: node.id === systemId,
|
||||
};
|
||||
}),
|
||||
);
|
||||
}, []);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ForwardedRef, useImperativeHandle } from 'react';
|
||||
import { ForwardedRef, useImperativeHandle, useRef } from 'react';
|
||||
import {
|
||||
CommandAddConnections,
|
||||
CommandAddSystems,
|
||||
@@ -18,6 +18,9 @@ import {
|
||||
CommandUpdateSystems,
|
||||
MapHandlers,
|
||||
} from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
|
||||
import { useMapEventListener } from '@/hooks/Mapper/events';
|
||||
|
||||
import {
|
||||
useCommandsCharacters,
|
||||
useCommandsConnections,
|
||||
@@ -26,6 +29,7 @@ import {
|
||||
useMapInit,
|
||||
useMapRemoveSystems,
|
||||
useMapUpdateSystems,
|
||||
useCenterSystem,
|
||||
useSelectSystem,
|
||||
} from './api';
|
||||
import { OnMapSelectionChange } from '@/hooks/Mapper/components/map/map.types.ts';
|
||||
@@ -35,8 +39,12 @@ export const useMapHandlers = (ref: ForwardedRef<MapHandlers>, onSelectionChange
|
||||
const mapAddSystems = useMapAddSystems();
|
||||
const mapUpdateSystems = useMapUpdateSystems();
|
||||
const removeSystems = useMapRemoveSystems(onSelectionChange);
|
||||
const centerSystem = useCenterSystem();
|
||||
const selectSystem = useSelectSystem();
|
||||
|
||||
const selectRef = useRef({ onSelectionChange });
|
||||
selectRef.current = { onSelectionChange };
|
||||
|
||||
const { addConnections, removeConnections, updateConnection } = useCommandsConnections();
|
||||
const { mapUpdated, killsUpdated } = useMapCommands();
|
||||
const { charactersUpdated, presentCharacters, characterAdded, characterRemoved, characterUpdated } =
|
||||
@@ -52,16 +60,13 @@ export const useMapHandlers = (ref: ForwardedRef<MapHandlers>, onSelectionChange
|
||||
mapInit(data as CommandInit);
|
||||
break;
|
||||
case Commands.addSystems:
|
||||
mapAddSystems(data as CommandAddSystems);
|
||||
break;
|
||||
case Commands.updateSystems:
|
||||
mapUpdateSystems(data as CommandUpdateSystems);
|
||||
break;
|
||||
case Commands.removeSystems:
|
||||
removeSystems(data as CommandRemoveSystems);
|
||||
break;
|
||||
case Commands.addConnections:
|
||||
addConnections(data as CommandAddConnections);
|
||||
break;
|
||||
case Commands.removeConnections:
|
||||
removeConnections(data as CommandRemoveConnections);
|
||||
@@ -91,14 +96,32 @@ export const useMapHandlers = (ref: ForwardedRef<MapHandlers>, onSelectionChange
|
||||
killsUpdated(data as CommandKillsUpdated);
|
||||
break;
|
||||
|
||||
case Commands.centerSystem:
|
||||
setTimeout(() => {
|
||||
const systemId = `${data}`;
|
||||
centerSystem(systemId as CommandSelectSystem);
|
||||
}, 100);
|
||||
break;
|
||||
|
||||
case Commands.selectSystem:
|
||||
selectSystem(data as CommandSelectSystem);
|
||||
setTimeout(() => {
|
||||
const systemId = `${data}`;
|
||||
selectRef.current.onSelectionChange({
|
||||
systems: [systemId],
|
||||
connections: [],
|
||||
});
|
||||
selectSystem(systemId as CommandSelectSystem);
|
||||
}, 100);
|
||||
break;
|
||||
|
||||
case Commands.routes:
|
||||
// do nothing here
|
||||
break;
|
||||
|
||||
case Commands.linkSignatureToSystem:
|
||||
// do nothing here
|
||||
break;
|
||||
|
||||
default:
|
||||
console.warn(`Map handlers: Unknown command: ${type}`, data);
|
||||
break;
|
||||
@@ -108,4 +131,20 @@ 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;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Button } from 'primereact/button';
|
||||
import { OutCommand } from '@/hooks/Mapper/types';
|
||||
import { IconField } from 'primereact/iconfield';
|
||||
import { LabelsManager } from '@/hooks/Mapper/utils/labelsManager.ts';
|
||||
import { WdImageSize, WdImgButton } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { WdImageSize, WdImgButton, TooltipPosition } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
interface SystemCustomLabelDialog {
|
||||
systemId: string;
|
||||
@@ -79,14 +79,14 @@ export const SystemCustomLabelDialog = ({ systemId, visible, setVisible }: Syste
|
||||
|
||||
// @ts-ignore
|
||||
const handleInput = useCallback(e => {
|
||||
e.target.value = e.target.value.toUpperCase().replace(/[^A-Z0-9]/g, '');
|
||||
e.target.value = e.target.value.toUpperCase().replace(/[^A-Z0-9[\](){}]/g, '');
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
header="Edit label"
|
||||
visible={visible}
|
||||
draggable={false}
|
||||
draggable={true}
|
||||
style={{ width: '250px' }}
|
||||
onHide={onHide}
|
||||
onShow={onShow}
|
||||
@@ -100,9 +100,13 @@ export const SystemCustomLabelDialog = ({ systemId, visible, setVisible }: Syste
|
||||
<IconField>
|
||||
{label !== '' && (
|
||||
<WdImgButton
|
||||
className="pi pi-trash p-input-icon"
|
||||
className="pi pi-trash text-red-400"
|
||||
textSize={WdImageSize.large}
|
||||
tooltip={{ content: 'Reset label' }}
|
||||
tooltip={{
|
||||
content: 'Remove custom label',
|
||||
className: 'pi p-input-icon',
|
||||
position: TooltipPosition.top,
|
||||
}}
|
||||
onClick={handleReset}
|
||||
/>
|
||||
)}
|
||||
@@ -111,7 +115,7 @@ export const SystemCustomLabelDialog = ({ systemId, visible, setVisible }: Syste
|
||||
aria-describedby="username-help"
|
||||
autoComplete="off"
|
||||
value={label}
|
||||
maxLength={3}
|
||||
maxLength={5}
|
||||
onChange={e => setLabel(e.target.value)}
|
||||
// @ts-expect-error
|
||||
ref={inputRef}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
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();
|
||||
|
||||
const ref = useRef({ outCommand });
|
||||
ref.current = { outCommand };
|
||||
|
||||
const handleHide = useCallback(() => {
|
||||
setVisible(false);
|
||||
}, [setVisible]);
|
||||
|
||||
const handleSelect = useCallback(
|
||||
(signature: SystemSignature) => {
|
||||
if (!signature) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { outCommand } = ref.current;
|
||||
|
||||
outCommand({
|
||||
type: OutCommand.linkSignatureToSystem,
|
||||
data: {
|
||||
...data,
|
||||
signature_eve_id: signature.eve_id,
|
||||
},
|
||||
});
|
||||
setVisible(false);
|
||||
},
|
||||
[data, 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>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from './SystemLinkSignatureDialog';
|
||||
@@ -90,7 +90,7 @@ export const SystemSettingsDialog = ({ systemId, visible, setVisible }: SystemSe
|
||||
}, []);
|
||||
|
||||
const handleInput = useCallback((e: any) => {
|
||||
e.target.value = e.target.value.toUpperCase().replace(/[^A-Z0-9]/g, '');
|
||||
e.target.value = e.target.value.toUpperCase().replace(/[^A-Z0-9[\](){}]/g, '');
|
||||
}, []);
|
||||
|
||||
return (
|
||||
@@ -160,7 +160,7 @@ export const SystemSettingsDialog = ({ systemId, visible, setVisible }: SystemSe
|
||||
aria-describedby="label"
|
||||
autoComplete="off"
|
||||
value={label}
|
||||
maxLength={3}
|
||||
maxLength={5}
|
||||
onChange={e => setLabel(e.target.value)}
|
||||
onInput={handleInput}
|
||||
/>
|
||||
|
||||
@@ -2,3 +2,4 @@ export * from './Widget';
|
||||
export * from './WidgetsGrid';
|
||||
export * from './SystemSettingsDialog';
|
||||
export * from './SystemCustomLabelDialog';
|
||||
export * from './SystemLinkSignatureDialog';
|
||||
|
||||
@@ -91,7 +91,7 @@ export const RoutesList = ({ data, onContextMenu }: RoutesListProps) => {
|
||||
const { mapRef } = useMapRootState();
|
||||
|
||||
const handleClick = useCallback(
|
||||
(systemId: number) => mapRef.current?.command(Commands.selectSystem, systemId.toString()),
|
||||
(systemId: number) => mapRef.current?.command(Commands.centerSystem, systemId.toString()),
|
||||
[mapRef],
|
||||
);
|
||||
|
||||
|
||||
@@ -13,9 +13,10 @@ export const SystemInfoContent = ({ systemId }: SystemInfoContentProps) => {
|
||||
data: { systems, wormholesData },
|
||||
} = useMapRootState();
|
||||
|
||||
const sys = getSystemById(systems, systemId)!;
|
||||
const sys = getSystemById(systems, systemId)! || {};
|
||||
const { description } = sys;
|
||||
const { system_class, region_name, constellation_name, statics, effect_name, effect_power } = sys.system_static_info;
|
||||
const { system_class, region_name, constellation_name, statics, effect_name, effect_power } =
|
||||
sys.system_static_info || {};
|
||||
const isWH = isWormholeSpace(system_class);
|
||||
const sortedStatics = useMemo(() => sortWHClasses(wormholesData, statics), [wormholesData, statics]);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { useClipboard } from '@/hooks/Mapper/hooks/useClipboard';
|
||||
import { parseSignatures } from '@/hooks/Mapper/helpers';
|
||||
import { OutCommand } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { Commands, OutCommand } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { WdTooltip, WdTooltipHandlers } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
import { DataTable, DataTableRowMouseEvent, SortOrder } from 'primereact/datatable';
|
||||
import { DataTable, DataTableRowClickEvent, DataTableRowMouseEvent, SortOrder } from 'primereact/datatable';
|
||||
import { Column } from 'primereact/column';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import useRefState from 'react-usestateref';
|
||||
@@ -22,11 +22,14 @@ import {
|
||||
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/helpers';
|
||||
import {
|
||||
renderIcon,
|
||||
renderName,
|
||||
renderInfoColumn,
|
||||
renderTimeLeft,
|
||||
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/renders';
|
||||
// import { PrimeIcons } from 'primereact/api';
|
||||
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';
|
||||
|
||||
type SystemSignaturesSortSettings = {
|
||||
sortField: string;
|
||||
@@ -41,13 +44,18 @@ const SORT_DEFAULT_VALUES: SystemSignaturesSortSettings = {
|
||||
interface SystemSignaturesContentProps {
|
||||
systemId: string;
|
||||
settings: Setting[];
|
||||
selectable?: boolean;
|
||||
onSelect?: (signature: 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[]>([]);
|
||||
const [selectedSignatures, setSelectedSignatures] = useState<SystemSignature[]>([]);
|
||||
const [nameColumnWidth, setNameColumnWidth] = useState('auto');
|
||||
const [parsedSignatures, setParsedSignatures] = useState<SystemSignature[]>([]);
|
||||
const [askUser, setAskUser] = useState(false);
|
||||
const [selectedSignature, setSelectedSignature] = useState<SystemSignature | null>(null);
|
||||
|
||||
const [hoveredSig, setHoveredSig] = useState<SystemSignature | null>(null);
|
||||
|
||||
@@ -86,12 +94,33 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures
|
||||
data: { system_id: systemId },
|
||||
});
|
||||
|
||||
setAskUser(false);
|
||||
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[]) => {
|
||||
const { added, updated, removed } = getActualSigs(signaturesRef.current, newSignatures);
|
||||
async (newSignatures: SystemSignature[], updateOnly: boolean) => {
|
||||
const { added, updated, removed } = getActualSigs(signaturesRef.current, newSignatures, updateOnly);
|
||||
|
||||
const { signatures: updatedSignatures } = await outCommand({
|
||||
type: OutCommand.updateSignatures,
|
||||
@@ -110,43 +139,96 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures
|
||||
);
|
||||
|
||||
const handleDeleteSelected = useCallback(async () => {
|
||||
if (selectable) {
|
||||
return;
|
||||
}
|
||||
if (selectedSignatures.length === 0) {
|
||||
return;
|
||||
}
|
||||
const selectedSignaturesEveIds = selectedSignatures.map(x => x.eve_id);
|
||||
await handleUpdateSignatures(signatures.filter(x => !selectedSignaturesEveIds.includes(x.eve_id)));
|
||||
}, [handleUpdateSignatures, signatures, selectedSignatures]);
|
||||
await handleUpdateSignatures(
|
||||
signatures.filter(x => !selectedSignaturesEveIds.includes(x.eve_id)),
|
||||
false,
|
||||
);
|
||||
}, [handleUpdateSignatures, selectable, signatures, selectedSignatures]);
|
||||
|
||||
const handleSelectAll = useCallback(() => {
|
||||
setSelectedSignatures(signatures);
|
||||
}, [signatures]);
|
||||
|
||||
const handleReplaceAll = useCallback(() => {
|
||||
handleUpdateSignatures(parsedSignatures, false);
|
||||
setAskUser(false);
|
||||
}, [parsedSignatures, handleUpdateSignatures]);
|
||||
|
||||
const handleUpdateOnly = useCallback(() => {
|
||||
handleUpdateSignatures(parsedSignatures, true);
|
||||
setAskUser(false);
|
||||
}, [parsedSignatures, handleUpdateSignatures]);
|
||||
|
||||
const handleSelectSignatures = useCallback(
|
||||
// TODO still will be good to define types if we use typescript
|
||||
// @ts-ignore
|
||||
e => {
|
||||
if (selectable) {
|
||||
onSelect?.(e.value);
|
||||
} else {
|
||||
setSelectedSignatures(e.value);
|
||||
}
|
||||
},
|
||||
[onSelect, selectable],
|
||||
);
|
||||
|
||||
useHotkey(true, ['a'], handleSelectAll);
|
||||
|
||||
useHotkey(false, ['Backspace', 'Delete'], handleDeleteSelected);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!clipboardContent) {
|
||||
return;
|
||||
}
|
||||
|
||||
const signatures = parseSignatures(
|
||||
const newSignatures = parseSignatures(
|
||||
clipboardContent,
|
||||
settings.map(x => x.key),
|
||||
);
|
||||
|
||||
handleUpdateSignatures(signatures);
|
||||
}, [clipboardContent]);
|
||||
const { removed } = getActualSigs(signaturesRef.current, newSignatures, false);
|
||||
|
||||
if (!signaturesRef.current || !signaturesRef.current.length || !removed.length) {
|
||||
handleUpdateSignatures(newSignatures, false);
|
||||
} else {
|
||||
setParsedSignatures(newSignatures);
|
||||
setAskUser(true);
|
||||
}
|
||||
}, [clipboardContent, selectable]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!systemId) {
|
||||
setSignatures([]);
|
||||
setAskUser(false);
|
||||
return;
|
||||
}
|
||||
|
||||
handleGetSignatures();
|
||||
}, [systemId]);
|
||||
|
||||
useMapEventListener(event => {
|
||||
switch (event.name) {
|
||||
case Commands.signaturesUpdated:
|
||||
if (event.data?.toString() !== systemId.toString()) {
|
||||
return;
|
||||
}
|
||||
|
||||
handleGetSignatures();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const observer = new ResizeObserver(handleResize);
|
||||
if (tableRef.current) {
|
||||
@@ -175,107 +257,147 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures
|
||||
setHoveredSig(null);
|
||||
}, []);
|
||||
|
||||
// const renderToolbar = (/*row: SystemSignature*/) => {
|
||||
// return (
|
||||
// <div className="flex justify-end items-center gap-2">
|
||||
// <span className={clsx(PrimeIcons.PENCIL, 'text-[10px]')}></span>
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
const renderToolbar = (/*row: SystemSignature*/) => {
|
||||
return (
|
||||
<div className="flex justify-end items-center gap-2 mr-[4px]">
|
||||
<WdTooltipWrapper content="To Edit Signature do double click">
|
||||
<span className={clsx(PrimeIcons.PENCIL, 'text-[10px]')}></span>
|
||||
</WdTooltipWrapper>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const [showSignatureSettings, setShowSignatureSettings] = useState(false);
|
||||
|
||||
const handleRowClick = (e: DataTableRowClickEvent) => {
|
||||
setSelectedSignature(e.data as SystemSignature);
|
||||
setShowSignatureSettings(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<div ref={tableRef} className="h-full">
|
||||
{filteredSignatures.length === 0 ? (
|
||||
<div className="w-full h-full flex justify-center items-center select-none text-stone-400/80 text-sm">
|
||||
No signatures
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<DataTable
|
||||
className={classes.Table}
|
||||
value={filteredSignatures}
|
||||
size="small"
|
||||
selectionMode="multiple"
|
||||
selection={selectedSignatures}
|
||||
metaKeySelection
|
||||
onSelectionChange={e => setSelectedSignatures(e.value)}
|
||||
dataKey="eve_id"
|
||||
tableClassName="w-full select-none"
|
||||
resizableColumns={false}
|
||||
rowHover
|
||||
selectAll
|
||||
sortField={sortSettings.sortField}
|
||||
sortOrder={sortSettings.sortOrder}
|
||||
onSort={event => setSortSettings(() => ({ sortField: event.sortField, sortOrder: event.sortOrder }))}
|
||||
onRowMouseEnter={compact || medium ? handleEnterRow : undefined}
|
||||
onRowMouseLeave={compact || medium ? handleLeaveRow : undefined}
|
||||
rowClassName={row => {
|
||||
if (selectedSignatures.some(x => x.eve_id === row.eve_id)) {
|
||||
return clsx(classes.TableRowCompact, 'bg-amber-500/50 hover:bg-amber-500/70 transition duration-200');
|
||||
}
|
||||
<>
|
||||
<div ref={tableRef} className={'h-full '}>
|
||||
{filteredSignatures.length === 0 ? (
|
||||
<div className="w-full h-full flex justify-center items-center select-none text-stone-400/80 text-sm">
|
||||
No signatures
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{/* @ts-ignore */}
|
||||
<DataTable
|
||||
className={classes.Table}
|
||||
value={filteredSignatures}
|
||||
size="small"
|
||||
selectionMode={selectable ? 'single' : 'multiple'}
|
||||
selection={selectedSignatures}
|
||||
metaKeySelection
|
||||
onSelectionChange={handleSelectSignatures}
|
||||
dataKey="eve_id"
|
||||
tableClassName="w-full select-none"
|
||||
resizableColumns={false}
|
||||
onRowDoubleClick={handleRowClick}
|
||||
rowHover
|
||||
selectAll
|
||||
sortField={sortSettings.sortField}
|
||||
sortOrder={sortSettings.sortOrder}
|
||||
onSort={event => setSortSettings(() => ({ sortField: event.sortField, sortOrder: event.sortOrder }))}
|
||||
onRowMouseEnter={compact || medium ? handleEnterRow : undefined}
|
||||
onRowMouseLeave={compact || medium ? handleLeaveRow : undefined}
|
||||
rowClassName={row => {
|
||||
if (selectedSignatures.some(x => x.eve_id === row.eve_id)) {
|
||||
return clsx(classes.TableRowCompact, 'bg-amber-500/50 hover:bg-amber-500/70 transition duration-200');
|
||||
}
|
||||
|
||||
const dateClass = getRowColorByTimeLeft(row.updated_at ? new Date(row.updated_at) : undefined);
|
||||
if (!dateClass) {
|
||||
return clsx(classes.TableRowCompact, 'hover:bg-purple-400/20 transition duration-200');
|
||||
}
|
||||
const dateClass = getRowColorByTimeLeft(row.updated_at ? new Date(row.updated_at) : undefined);
|
||||
if (!dateClass) {
|
||||
return clsx(classes.TableRowCompact, 'hover:bg-purple-400/20 transition duration-200');
|
||||
}
|
||||
|
||||
return clsx(classes.TableRowCompact, dateClass);
|
||||
}}
|
||||
>
|
||||
<Column
|
||||
bodyClassName="p-0 px-1"
|
||||
field="group"
|
||||
body={renderIcon}
|
||||
style={{ maxWidth: 26, minWidth: 26, width: 26, height: 25 }}
|
||||
></Column>
|
||||
return clsx(classes.TableRowCompact, dateClass);
|
||||
}}
|
||||
>
|
||||
<Column
|
||||
bodyClassName="p-0 px-1"
|
||||
field="group"
|
||||
body={x => renderIcon(x)}
|
||||
style={{ maxWidth: 26, minWidth: 26, width: 26, height: 25 }}
|
||||
></Column>
|
||||
|
||||
<Column
|
||||
field="eve_id"
|
||||
header="Id"
|
||||
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
|
||||
style={{ maxWidth: 72, minWidth: 72, width: 72 }}
|
||||
sortable
|
||||
></Column>
|
||||
<Column
|
||||
field="group"
|
||||
header="Group"
|
||||
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
|
||||
hidden={compact}
|
||||
sortable
|
||||
></Column>
|
||||
<Column
|
||||
field="name"
|
||||
header="Name"
|
||||
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
|
||||
body={renderName}
|
||||
style={{ maxWidth: nameColumnWidth }}
|
||||
hidden={compact || medium}
|
||||
sortable
|
||||
></Column>
|
||||
<Column
|
||||
field="updated_at"
|
||||
header="Updated"
|
||||
dataType="date"
|
||||
bodyClassName="w-[80px] text-ellipsis overflow-hidden whitespace-nowrap"
|
||||
body={renderTimeLeft}
|
||||
sortable
|
||||
></Column>
|
||||
<Column
|
||||
field="eve_id"
|
||||
header="Id"
|
||||
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
|
||||
style={{ maxWidth: 72, minWidth: 72, width: 72 }}
|
||||
sortable
|
||||
></Column>
|
||||
<Column
|
||||
field="group"
|
||||
header="Group"
|
||||
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
|
||||
hidden={compact}
|
||||
sortable
|
||||
></Column>
|
||||
<Column
|
||||
field="info"
|
||||
// header="Info"
|
||||
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
|
||||
body={renderInfoColumn}
|
||||
style={{ maxWidth: nameColumnWidth }}
|
||||
hidden={compact || medium}
|
||||
></Column>
|
||||
<Column
|
||||
field="updated_at"
|
||||
header="Updated"
|
||||
dataType="date"
|
||||
bodyClassName="w-[70px] text-ellipsis overflow-hidden whitespace-nowrap"
|
||||
body={renderTimeLeft}
|
||||
sortable
|
||||
></Column>
|
||||
|
||||
{/*<Column*/}
|
||||
{/* bodyClassName="p-0 pl-1 pr-2"*/}
|
||||
{/* field="group"*/}
|
||||
{/* body={renderToolbar}*/}
|
||||
{/* headerClassName={headerClasses}*/}
|
||||
{/* style={{ maxWidth: 26, minWidth: 26, width: 26 }}*/}
|
||||
{/*></Column>*/}
|
||||
</DataTable>
|
||||
</>
|
||||
)}
|
||||
<WdTooltip
|
||||
className="bg-stone-900/95 text-slate-50"
|
||||
ref={tooltipRef}
|
||||
content={hoveredSig ? <SignatureView {...hoveredSig} /> : null}
|
||||
/>
|
||||
</div>
|
||||
<Column
|
||||
bodyClassName="p-0 pl-1 pr-2"
|
||||
field="group"
|
||||
body={renderToolbar}
|
||||
// headerClassName={headerClasses}
|
||||
style={{ maxWidth: 26, minWidth: 26, width: 26 }}
|
||||
></Column>
|
||||
</DataTable>
|
||||
</>
|
||||
)}
|
||||
<WdTooltip
|
||||
className="bg-stone-900/95 text-slate-50"
|
||||
ref={tooltipRef}
|
||||
content={hoveredSig ? <SignatureView {...hoveredSig} /> : null}
|
||||
/>
|
||||
|
||||
<SignatureSettings
|
||||
systemId={systemId}
|
||||
show={showSignatureSettings}
|
||||
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">
|
||||
<div className="absolute top-0 left-0 w-full h-full flex flex-col items-center justify-center">
|
||||
<div className="text-stone-400/80 text-sm">
|
||||
<div className="flex flex-col text-center gap-2">
|
||||
<button className="p-button p-component p-button-outlined p-button-sm btn-wide">
|
||||
<span className="p-button-label p-c" onClick={handleUpdateOnly}>
|
||||
Update
|
||||
</span>
|
||||
</button>
|
||||
<button className="p-button p-component p-button-outlined p-button-sm btn-wide">
|
||||
<span className="p-button-label p-c" onClick={handleReplaceAll}>
|
||||
Update & Delete missing
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ import { getState } from './getState.ts';
|
||||
export const getActualSigs = (
|
||||
oldSignatures: SystemSignature[],
|
||||
newSignatures: SystemSignature[],
|
||||
updateOnly: boolean,
|
||||
): { added: SystemSignature[]; updated: SystemSignature[]; removed: SystemSignature[] } => {
|
||||
const updated: SystemSignature[] = [];
|
||||
const removed: SystemSignature[] = [];
|
||||
@@ -20,7 +21,9 @@ export const getActualSigs = (
|
||||
updated.push({ ...oldSig, group: newSig.group, name: newSig.name });
|
||||
}
|
||||
} else {
|
||||
removed.push(oldSig);
|
||||
if (!updateOnly) {
|
||||
removed.push(oldSig);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ export const getState = (_: string[], newSig: SystemSignature) => {
|
||||
let state = -1;
|
||||
if (!newSig.group || newSig.group === '') {
|
||||
state = 0;
|
||||
} else if (!!newSig.group && newSig.group !== '' && newSig.name === '') {
|
||||
} else if (!newSig.name || newSig.name === '') {
|
||||
state = 1;
|
||||
} else if (!!newSig.group && newSig.group !== '' && newSig.name !== '') {
|
||||
} else if (newSig.name !== '') {
|
||||
state = 2;
|
||||
}
|
||||
return state;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export * from './renderIcon';
|
||||
export * from './renderName';
|
||||
export * from './renderTimeLeft';
|
||||
export * from './renderLinkedSystem';
|
||||
export * from './renderInfoColumn';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { SignatureGroup, SystemSignature } from '@/hooks/Mapper/types';
|
||||
import { GroupType, SignatureGroup, SystemSignature } from '@/hooks/Mapper/types';
|
||||
import { GROUPS } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/constants.ts';
|
||||
|
||||
export const renderIcon = (row: SystemSignature) => {
|
||||
export const renderIcon = (row: SystemSignature, customSize?: Omit<GroupType, 'icon' | 'id'>) => {
|
||||
if (row.group == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -13,7 +13,7 @@ export const renderIcon = (row: SystemSignature) => {
|
||||
|
||||
return (
|
||||
<div className="flex justify-center items-center">
|
||||
<img src={group.icon} style={{ width: group.w, height: group.h }} />
|
||||
<img src={group.icon} style={{ width: customSize?.w ?? group.w, height: customSize?.h ?? group.h }} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.whFontSize {
|
||||
font-size: 11px !important;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import { SignatureGroup, SystemSignature } from '@/hooks/Mapper/types';
|
||||
import { SystemViewStandalone, WHClassView } from '@/hooks/Mapper/components/ui-kit';
|
||||
import clsx from 'clsx';
|
||||
import { renderName } from './renderName.tsx';
|
||||
import classes from './renderInfoColumn.module.scss';
|
||||
|
||||
export const renderInfoColumn = (row: SystemSignature) => {
|
||||
if (!row.group || row.group === SignatureGroup.Wormhole) {
|
||||
return (
|
||||
<div className="flex justify-start items-center gap-[6px]">
|
||||
{row.type && (
|
||||
<WHClassView
|
||||
className="text-[11px]"
|
||||
classNameWh={classes.whFontSize}
|
||||
highlightName
|
||||
hideWhClass={!!row.linked_system}
|
||||
whClassName={row.type}
|
||||
noOffset
|
||||
useShortTitle
|
||||
/>
|
||||
)}
|
||||
|
||||
{row.linked_system && (
|
||||
<>
|
||||
{/*<span className="w-4 h-4 hero-arrow-long-right"></span>*/}
|
||||
<span title={row.linked_system?.solar_system_name}>
|
||||
<SystemViewStandalone
|
||||
className={clsx('select-none text-center cursor-context-menu')}
|
||||
hideRegion
|
||||
{...row.linked_system}
|
||||
/>
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (row.description != null && row.description.length > 0) {
|
||||
return <span title={row.description}>{row.description}</span>;
|
||||
}
|
||||
|
||||
return renderName(row);
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -6,6 +6,8 @@ import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
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";
|
||||
|
||||
export interface MapRootContentProps {}
|
||||
|
||||
@@ -15,9 +17,13 @@ export const MapRootContent = ({}: MapRootContentProps) => {
|
||||
const { isShowMenu } = interfaceSettings;
|
||||
|
||||
const [showOnTheMap, setShowOnTheMap] = useState(false);
|
||||
const [showMapSettings, setShowMapSettings] = useState(false);
|
||||
const mapInterface = <MapInterface />;
|
||||
|
||||
const handleShowOnTheMap = useCallback(() => setShowOnTheMap(true), []);
|
||||
const handleShowMapSettings = useCallback(() => setShowMapSettings(true), []);
|
||||
|
||||
useSkipContextMenu();
|
||||
|
||||
return (
|
||||
<Layout map={<MapWrapper refn={mapRef} />}>
|
||||
@@ -28,18 +34,19 @@ export const MapRootContent = ({}: MapRootContentProps) => {
|
||||
{mapInterface}
|
||||
</div>
|
||||
<div className="absolute top-0 right-0 w-14 h-[calc(100%+3.5rem)] pointer-events-auto">
|
||||
<RightBar onShowOnTheMap={handleShowOnTheMap} />
|
||||
<RightBar onShowOnTheMap={handleShowOnTheMap} onShowMapSettings={handleShowMapSettings} />
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="absolute top-0 left-14 w-[calc(100%-3.5rem)] h-[calc(100%-3.5rem)] pointer-events-none">
|
||||
<Topbar>
|
||||
<MapContextMenu onShowOnTheMap={handleShowOnTheMap} />
|
||||
<MapContextMenu onShowOnTheMap={handleShowOnTheMap} onShowMapSettings={handleShowMapSettings} />
|
||||
</Topbar>
|
||||
{mapInterface}
|
||||
</div>
|
||||
)}
|
||||
<OnTheMap show={showOnTheMap} onHide={() => setShowOnTheMap(false)} />
|
||||
<MapSettings show={showMapSettings} onHide={() => setShowMapSettings(false)} />
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -8,10 +8,11 @@ import { MenuItem } from 'primereact/menuitem';
|
||||
|
||||
export interface MapContextMenuProps {
|
||||
onShowOnTheMap?: () => void;
|
||||
onShowMapSettings?: () => void;
|
||||
}
|
||||
|
||||
export const MapContextMenu = ({ onShowOnTheMap }: MapContextMenuProps) => {
|
||||
const { outCommand, interfaceSettings, setInterfaceSettings } = useMapRootState();
|
||||
export const MapContextMenu = ({ onShowOnTheMap, onShowMapSettings }: MapContextMenuProps) => {
|
||||
const { outCommand, setInterfaceSettings } = useMapRootState();
|
||||
|
||||
const menuRight = useRef<Menu>(null);
|
||||
|
||||
@@ -22,13 +23,6 @@ export const MapContextMenu = ({ onShowOnTheMap }: MapContextMenuProps) => {
|
||||
});
|
||||
}, [outCommand]);
|
||||
|
||||
const toggleMinimap = useCallback(() => {
|
||||
setInterfaceSettings(x => ({
|
||||
...x,
|
||||
isShowMinimap: !x.isShowMinimap,
|
||||
}));
|
||||
}, [setInterfaceSettings]);
|
||||
|
||||
const items = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
@@ -43,9 +37,9 @@ export const MapContextMenu = ({ onShowOnTheMap }: MapContextMenuProps) => {
|
||||
},
|
||||
{ separator: true },
|
||||
{
|
||||
label: interfaceSettings.isShowMinimap ? 'Hide minimap' : 'Show minimap',
|
||||
icon: `pi ${interfaceSettings.isShowMinimap ? 'pi-eye-slash' : 'pi-eye'}`,
|
||||
command: toggleMinimap,
|
||||
label: 'Settings',
|
||||
icon: `pi pi-cog`,
|
||||
command: onShowMapSettings,
|
||||
},
|
||||
{
|
||||
label: 'Dock menu',
|
||||
@@ -57,7 +51,7 @@ export const MapContextMenu = ({ onShowOnTheMap }: MapContextMenuProps) => {
|
||||
})),
|
||||
},
|
||||
] as MenuItem[];
|
||||
}, [handleAddCharacter, interfaceSettings.isShowMinimap, onShowOnTheMap, setInterfaceSettings, toggleMinimap]);
|
||||
}, [handleAddCharacter, onShowMapSettings, onShowOnTheMap, setInterfaceSettings]);
|
||||
|
||||
return (
|
||||
<div className="ml-1">
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.CheckboxContainer {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
align-items: center;
|
||||
|
||||
& > span:nth-child(1) {
|
||||
color: var(--gray-200);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
& > :nth-child(2){
|
||||
border-bottom: 2px dotted #3f3f3f;
|
||||
height: 2px;
|
||||
margin: 0 12px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Уменьшение размеров InputSwitch с использованием глобальных стилей */
|
||||
.smallInputSwitch {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
:global {
|
||||
.p-inputswitch {
|
||||
height: 1rem;
|
||||
width: 2rem;
|
||||
&.p-inputswitch-checked {
|
||||
.p-inputswitch-slider::before {
|
||||
transform: translateX(1rem);
|
||||
}
|
||||
}
|
||||
|
||||
&.p-highlight .p-inputswitch-slider:before {
|
||||
transform: translateX(1rem);
|
||||
}
|
||||
|
||||
.p-inputswitch-slider::before {
|
||||
width: 0.8rem;
|
||||
height: 0.8rem;
|
||||
margin-top: -0.4rem;
|
||||
margin-left: -3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
import styles from './MapSettings.module.scss';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { TabPanel, TabView } from 'primereact/tabview';
|
||||
import { PrettySwitchbox } from './components';
|
||||
import { InterfaceStoredSettings, InterfaceStoredSettingsProps, useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { OutCommand } from '@/hooks/Mapper/types';
|
||||
|
||||
export enum UserSettingsRemoteProps {
|
||||
link_signature_on_splash = 'link_signature_on_splash',
|
||||
select_on_spash = 'select_on_spash',
|
||||
delete_connection_with_sigs = 'delete_connection_with_sigs',
|
||||
}
|
||||
|
||||
export const DEFAULT_REMOTE_SETTINGS = {
|
||||
[UserSettingsRemoteProps.link_signature_on_splash]: false,
|
||||
[UserSettingsRemoteProps.select_on_spash]: false,
|
||||
[UserSettingsRemoteProps.delete_connection_with_sigs]: false,
|
||||
};
|
||||
|
||||
export const UserSettingsRemoteList = [
|
||||
UserSettingsRemoteProps.link_signature_on_splash,
|
||||
UserSettingsRemoteProps.select_on_spash,
|
||||
UserSettingsRemoteProps.delete_connection_with_sigs,
|
||||
];
|
||||
|
||||
export type UserSettingsRemote = {
|
||||
link_signature_on_splash: boolean;
|
||||
select_on_spash: boolean;
|
||||
delete_connection_with_sigs: boolean;
|
||||
};
|
||||
|
||||
export type UserSettings = UserSettingsRemote & InterfaceStoredSettings;
|
||||
|
||||
export interface MapSettingsProps {
|
||||
show: boolean;
|
||||
onHide: () => void;
|
||||
}
|
||||
|
||||
type CheckboxesList = {
|
||||
prop: keyof UserSettings;
|
||||
label: string;
|
||||
}[];
|
||||
|
||||
const COMMON_CHECKBOXES_PROPS: CheckboxesList = [
|
||||
{ prop: InterfaceStoredSettingsProps.isShowMinimap, label: 'Show Minimap' },
|
||||
];
|
||||
|
||||
const SYSTEMS_CHECKBOXES_PROPS: CheckboxesList = [
|
||||
{ prop: InterfaceStoredSettingsProps.isShowKSpace, label: 'Highlight Low/High-security systems' },
|
||||
{ prop: UserSettingsRemoteProps.select_on_spash, label: 'Auto-select splashed' },
|
||||
];
|
||||
|
||||
const SIGNATURES_CHECKBOXES_PROPS: CheckboxesList = [
|
||||
{ prop: UserSettingsRemoteProps.link_signature_on_splash, label: 'Link signature on splash' },
|
||||
];
|
||||
|
||||
const CONNECTIONS_CHECKBOXES_PROPS: CheckboxesList = [
|
||||
{ prop: UserSettingsRemoteProps.delete_connection_with_sigs, label: 'Delete connections to linked signatures' },
|
||||
];
|
||||
|
||||
const UI_CHECKBOXES_PROPS: CheckboxesList = [
|
||||
{ prop: InterfaceStoredSettingsProps.isShowMenu, label: 'Enable compact map menu bar' },
|
||||
];
|
||||
|
||||
export const MapSettings = ({ show, onHide }: MapSettingsProps) => {
|
||||
const [activeIndex, setActiveIndex] = useState(0);
|
||||
const { outCommand, interfaceSettings, setInterfaceSettings } = useMapRootState();
|
||||
const [userRemoteSettings, setUserRemoteSettings] = useState<UserSettingsRemote>({ ...DEFAULT_REMOTE_SETTINGS });
|
||||
|
||||
const mergedSettings = useMemo(() => {
|
||||
return {
|
||||
...interfaceSettings,
|
||||
...userRemoteSettings,
|
||||
};
|
||||
}, [userRemoteSettings, interfaceSettings]);
|
||||
|
||||
const handleShow = async () => {
|
||||
const { user_settings } = await outCommand({
|
||||
type: OutCommand.getUserSettings,
|
||||
data: null,
|
||||
});
|
||||
|
||||
setUserRemoteSettings({
|
||||
...user_settings,
|
||||
});
|
||||
};
|
||||
|
||||
const handleChangeChecked = useCallback(
|
||||
(prop: keyof UserSettings) => async (checked: boolean) => {
|
||||
// @ts-ignore
|
||||
if (UserSettingsRemoteList.includes(prop)) {
|
||||
const newRemoteSettings = {
|
||||
...userRemoteSettings,
|
||||
[prop]: checked,
|
||||
};
|
||||
|
||||
await outCommand({
|
||||
type: OutCommand.updateUserSettings,
|
||||
data: newRemoteSettings,
|
||||
});
|
||||
|
||||
setUserRemoteSettings(newRemoteSettings);
|
||||
return;
|
||||
}
|
||||
|
||||
setInterfaceSettings({
|
||||
...interfaceSettings,
|
||||
[prop]: checked,
|
||||
});
|
||||
},
|
||||
[interfaceSettings, outCommand, setInterfaceSettings, userRemoteSettings],
|
||||
);
|
||||
|
||||
const renderCheckboxesList = (list: CheckboxesList) => {
|
||||
return list.map(x => {
|
||||
return (
|
||||
<PrettySwitchbox
|
||||
key={x.prop}
|
||||
label={x.label}
|
||||
checked={mergedSettings[x.prop]}
|
||||
setChecked={handleChangeChecked(x.prop)}
|
||||
/>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
header="Map settings"
|
||||
visible={show}
|
||||
draggable={false}
|
||||
style={{ width: '550px' }}
|
||||
onShow={handleShow}
|
||||
onHide={() => {
|
||||
if (!show) {
|
||||
return;
|
||||
}
|
||||
|
||||
setActiveIndex(0);
|
||||
onHide();
|
||||
}}
|
||||
>
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className={styles.verticalTabsContainer}>
|
||||
<TabView
|
||||
activeIndex={activeIndex}
|
||||
onTabChange={e => setActiveIndex(e.index)}
|
||||
className={styles.verticalTabView}
|
||||
>
|
||||
<TabPanel header="Common" headerClassName={styles.verticalTabHeader}>
|
||||
<div className="w-full h-full flex flex-col gap-1">{renderCheckboxesList(COMMON_CHECKBOXES_PROPS)}</div>
|
||||
</TabPanel>
|
||||
<TabPanel header="Systems" headerClassName={styles.verticalTabHeader}>
|
||||
<div className="w-full h-full flex flex-col gap-1">
|
||||
{renderCheckboxesList(SYSTEMS_CHECKBOXES_PROPS)}
|
||||
</div>
|
||||
</TabPanel>
|
||||
<TabPanel header="Connections" headerClassName={styles.verticalTabHeader}>
|
||||
{renderCheckboxesList(CONNECTIONS_CHECKBOXES_PROPS)}
|
||||
</TabPanel>
|
||||
<TabPanel header="Signatures" headerClassName={styles.verticalTabHeader}>
|
||||
{renderCheckboxesList(SIGNATURES_CHECKBOXES_PROPS)}
|
||||
</TabPanel>
|
||||
<TabPanel header="User Interface" headerClassName={styles.verticalTabHeader}>
|
||||
{renderCheckboxesList(UI_CHECKBOXES_PROPS)}
|
||||
</TabPanel>
|
||||
</TabView>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
.CheckboxContainer {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
align-items: center;
|
||||
|
||||
& > span:nth-child(1) {
|
||||
color: var(--gray-200);
|
||||
font-size: 13px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
& > :nth-child(2){
|
||||
border-bottom: 2px dotted #3f3f3f;
|
||||
height: 1px;
|
||||
margin: 0 12px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Уменьшение размеров InputSwitch с использованием глобальных стилей */
|
||||
.smallInputSwitch {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
:global {
|
||||
.p-inputswitch {
|
||||
height: 1rem;
|
||||
width: 2rem;
|
||||
&.p-inputswitch-checked {
|
||||
.p-inputswitch-slider::before {
|
||||
transform: translateX(1rem);
|
||||
}
|
||||
}
|
||||
|
||||
&.p-highlight .p-inputswitch-slider:before {
|
||||
transform: translateX(1rem);
|
||||
}
|
||||
|
||||
.p-inputswitch-slider::before {
|
||||
width: 0.8rem;
|
||||
height: 0.8rem;
|
||||
margin-top: -0.4rem;
|
||||
margin-left: -3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import styles from './MapSettings.module.scss';
|
||||
import { WdCheckbox } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
interface PrettySwitchboxProps {
|
||||
checked: boolean;
|
||||
setChecked: (checked: boolean) => void;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export const PrettySwitchbox = ({ checked, setChecked, label }: PrettySwitchboxProps) => {
|
||||
return (
|
||||
<label className={styles.CheckboxContainer}>
|
||||
<span>{label}</span>
|
||||
<div />
|
||||
<div className={styles.smallInputSwitch}>
|
||||
<WdCheckbox size="m" label={''} value={checked} onChange={e => setChecked(e.checked ?? false)} />
|
||||
</div>
|
||||
</label>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from './PrettySwitchbox';
|
||||
@@ -0,0 +1 @@
|
||||
export * from './PrettySwitchbox';
|
||||
@@ -0,0 +1 @@
|
||||
export * from './MapSettings';
|
||||
@@ -8,9 +8,10 @@ import { TooltipPosition } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
interface RightBarProps {
|
||||
onShowOnTheMap?: () => void;
|
||||
onShowMapSettings?: () => void;
|
||||
}
|
||||
|
||||
export const RightBar = ({ onShowOnTheMap }: RightBarProps) => {
|
||||
export const RightBar = ({ onShowOnTheMap, onShowMapSettings }: RightBarProps) => {
|
||||
const { outCommand, interfaceSettings, setInterfaceSettings } = useMapRootState();
|
||||
|
||||
const isShowMinimap = interfaceSettings.isShowMinimap === undefined ? true : interfaceSettings.isShowMinimap;
|
||||
@@ -59,7 +60,7 @@ export const RightBar = ({ onShowOnTheMap }: RightBarProps) => {
|
||||
type="button"
|
||||
onClick={handleAddCharacter}
|
||||
>
|
||||
<i className="pi pi-user-plus text-lg"></i>
|
||||
<i className="pi pi-user-plus"></i>
|
||||
</button>
|
||||
</WdTooltipWrapper>
|
||||
|
||||
@@ -69,12 +70,22 @@ export const RightBar = ({ onShowOnTheMap }: RightBarProps) => {
|
||||
type="button"
|
||||
onClick={onShowOnTheMap}
|
||||
>
|
||||
<i className="pi pi-hashtag text-lg"></i>
|
||||
<i className="pi pi-hashtag"></i>
|
||||
</button>
|
||||
</WdTooltipWrapper>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-center mb-2 gap-1">
|
||||
<WdTooltipWrapper content="User settings" position={TooltipPosition.left}>
|
||||
<button
|
||||
className="btn bg-transparent text-gray-400 hover:text-white border-transparent hover:bg-transparent py-2 h-auto min-h-auto"
|
||||
type="button"
|
||||
onClick={onShowMapSettings}
|
||||
>
|
||||
<i className="pi pi-cog"></i>
|
||||
</button>
|
||||
</WdTooltipWrapper>
|
||||
|
||||
<WdTooltipWrapper
|
||||
content={
|
||||
interfaceSettings.isShowKSpace ? 'Hide highlighting Imperial Space' : 'Show highlighting Imperial Space'
|
||||
@@ -86,11 +97,7 @@ export const RightBar = ({ onShowOnTheMap }: RightBarProps) => {
|
||||
type="button"
|
||||
onClick={toggleKSpace}
|
||||
>
|
||||
{interfaceSettings.isShowKSpace ? (
|
||||
<i className="pi pi-star-fill text-lg"></i>
|
||||
) : (
|
||||
<i className="pi pi-star text-lg"></i>
|
||||
)}
|
||||
<i className={interfaceSettings.isShowKSpace ? 'hero-cloud-solid' : 'hero-cloud'}></i>
|
||||
</button>
|
||||
</WdTooltipWrapper>
|
||||
|
||||
@@ -100,7 +107,7 @@ export const RightBar = ({ onShowOnTheMap }: RightBarProps) => {
|
||||
type="button"
|
||||
onClick={toggleMinimap}
|
||||
>
|
||||
{isShowMinimap ? <i className="pi pi-eye text-lg"></i> : <i className="pi pi-eye-slash text-lg"></i>}
|
||||
<i className={isShowMinimap ? 'pi pi-eye' : 'pi pi-eye-slash'}></i>
|
||||
</button>
|
||||
</WdTooltipWrapper>
|
||||
|
||||
@@ -110,7 +117,7 @@ export const RightBar = ({ onShowOnTheMap }: RightBarProps) => {
|
||||
type="button"
|
||||
onClick={toggleMenu}
|
||||
>
|
||||
<i className="pi pi-window-minimize text-lg"></i>
|
||||
<i className="pi pi-window-minimize"></i>
|
||||
</button>
|
||||
</WdTooltipWrapper>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { createGenericContext } from '@/hooks/Mapper/utils/abstractContextProvider.tsx';
|
||||
|
||||
export interface SystemsSettingsProvider {
|
||||
systemId: string;
|
||||
}
|
||||
|
||||
const { Provider, useContextValue } = createGenericContext<SystemsSettingsProvider>();
|
||||
|
||||
export const SystemsSettingsProvider = Provider;
|
||||
export const useSystemsSettingsProvider = useContextValue;
|
||||
@@ -0,0 +1,81 @@
|
||||
.verticalTabsContainer {
|
||||
width: 100%;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.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: 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 {
|
||||
border-right: 4px solid var(--primary-color);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.p-tabview-panel {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
// import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { OutCommand, SignatureGroup, SystemSignature } from '@/hooks/Mapper/types';
|
||||
import { Controller, FormProvider, useForm } from 'react-hook-form';
|
||||
import {
|
||||
SignatureGroupContent,
|
||||
SignatureGroupSelect,
|
||||
} from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/components';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { SystemsSettingsProvider } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/Provider.tsx';
|
||||
import { Button } from 'primereact/button';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
|
||||
type SystemSignaturePrepared = Omit<SystemSignature, 'linked_system'> & { linked_system: string };
|
||||
|
||||
export interface MapSettingsProps {
|
||||
systemId: string;
|
||||
show: boolean;
|
||||
onHide: () => void;
|
||||
signatureData: SystemSignature | null;
|
||||
}
|
||||
|
||||
export const SignatureSettings = ({ systemId, show, onHide, signatureData }: MapSettingsProps) => {
|
||||
const { outCommand } = useMapRootState();
|
||||
|
||||
const handleShow = async () => {};
|
||||
const form = useForm<Partial<SystemSignaturePrepared>>({});
|
||||
|
||||
const handleSave = useCallback(async () => {
|
||||
if (!signatureData) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { group, ...values } = form.getValues();
|
||||
let out = { ...signatureData };
|
||||
|
||||
switch (group) {
|
||||
case SignatureGroup.Wormhole:
|
||||
if (values.linked_system) {
|
||||
await outCommand({
|
||||
type: OutCommand.linkSignatureToSystem,
|
||||
data: {
|
||||
signature_eve_id: signatureData.eve_id,
|
||||
solar_system_source: systemId,
|
||||
solar_system_target: values.linked_system,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (values.type != null) {
|
||||
out = { ...out, type: values.type };
|
||||
}
|
||||
|
||||
if (signatureData.group !== SignatureGroup.Wormhole) {
|
||||
out = { ...out, name: '' };
|
||||
}
|
||||
|
||||
break;
|
||||
case SignatureGroup.CosmicSignature:
|
||||
out = { ...out, type: '', name: '' };
|
||||
break;
|
||||
default:
|
||||
if (values.name != null) {
|
||||
out = { ...out, name: values.name ?? '' };
|
||||
}
|
||||
}
|
||||
|
||||
if (values.description != null) {
|
||||
out = { ...out, description: values.description };
|
||||
}
|
||||
|
||||
// Note: when type of signature changed from WH to other type - we should drop name
|
||||
if (
|
||||
group !== SignatureGroup.Wormhole && // new
|
||||
signatureData.group === SignatureGroup.Wormhole && // prev
|
||||
signatureData.linked_system
|
||||
) {
|
||||
await outCommand({
|
||||
type: OutCommand.unlinkSignature,
|
||||
data: { signature_eve_id: signatureData.eve_id, solar_system_source: systemId },
|
||||
});
|
||||
|
||||
out = { ...out, type: '' };
|
||||
}
|
||||
|
||||
if (group === SignatureGroup.Wormhole && signatureData.linked_system != null && values.linked_system === null) {
|
||||
await outCommand({
|
||||
type: OutCommand.unlinkSignature,
|
||||
data: { signature_eve_id: signatureData.eve_id, solar_system_source: systemId },
|
||||
});
|
||||
}
|
||||
|
||||
// Note: despite groups have optional type - this will always set
|
||||
out = { ...out, group: group! };
|
||||
|
||||
await outCommand({
|
||||
type: OutCommand.updateSignatures,
|
||||
data: {
|
||||
system_id: systemId,
|
||||
added: [],
|
||||
updated: [out],
|
||||
removed: [],
|
||||
},
|
||||
});
|
||||
|
||||
form.reset();
|
||||
onHide();
|
||||
}, [form, onHide, outCommand, signatureData, systemId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!signatureData) {
|
||||
form.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
const { linked_system, ...rest } = signatureData;
|
||||
|
||||
form.reset({
|
||||
linked_system: linked_system?.solar_system_id.toString() ?? undefined,
|
||||
...rest,
|
||||
});
|
||||
}, [form, signatureData]);
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
header={`Signature Edit [${signatureData?.eve_id}]`}
|
||||
visible={show}
|
||||
draggable={false}
|
||||
style={{ width: '390px' }}
|
||||
onShow={handleShow}
|
||||
onHide={() => {
|
||||
if (!show) {
|
||||
return;
|
||||
}
|
||||
|
||||
onHide();
|
||||
}}
|
||||
>
|
||||
<SystemsSettingsProvider initialValue={{ systemId }}>
|
||||
<FormProvider {...form}>
|
||||
<div className="flex flex-col gap-2 justify-between">
|
||||
<div className="w-full flex flex-col gap-1 p-1 min-h-[150px]">
|
||||
<label className="grid grid-cols-[100px_250px_1fr] gap-2 items-center text-[14px]">
|
||||
<span>Group:</span>
|
||||
<SignatureGroupSelect name="group" />
|
||||
</label>
|
||||
|
||||
<SignatureGroupContent />
|
||||
|
||||
<label className="grid grid-cols-[100px_250px_1fr] gap-2 items-center text-[14px]">
|
||||
<span>Description:</span>
|
||||
<Controller
|
||||
name="description"
|
||||
control={form.control}
|
||||
render={({ field }) => (
|
||||
<InputText placeholder="Type description" value={field.value} onChange={field.onChange} />
|
||||
)}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 justify-end">
|
||||
<Button onClick={handleSave} outlined size="small" label="Save"></Button>
|
||||
</div>
|
||||
</div>
|
||||
</FormProvider>
|
||||
</SystemsSettingsProvider>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
import { SignatureGroup, SystemSignature } from '@/hooks/Mapper/types';
|
||||
import { useSystemsSettingsProvider } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/Provider.tsx';
|
||||
import { SignatureGroupContentWormholes } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/components/SignatureGroupContentWormholes.tsx';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
|
||||
export interface SignatureGroupContentProps {}
|
||||
|
||||
export const SignatureGroupContent = ({}: SignatureGroupContentProps) => {
|
||||
const { watch, control } = useFormContext<SystemSignature>();
|
||||
const group = watch('group');
|
||||
|
||||
const {
|
||||
value: { systemId },
|
||||
} = useSystemsSettingsProvider();
|
||||
|
||||
if (!systemId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (group === SignatureGroup.Wormhole) {
|
||||
return (
|
||||
<>
|
||||
<SignatureGroupContentWormholes />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (group === SignatureGroup.CosmicSignature) {
|
||||
return <div></div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<label className="grid grid-cols-[100px_250px_1fr] gap-2 items-center text-[14px]">
|
||||
<span>Name:</span>
|
||||
<Controller
|
||||
name="name"
|
||||
control={control}
|
||||
render={({ field }) => <InputText placeholder="Name" value={field.value} onChange={field.onChange} />}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from './SignatureGroupContent';
|
||||
@@ -0,0 +1,18 @@
|
||||
import { SignatureWormholeTypeSelect } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/components/SignatureWormholeTypeSelect';
|
||||
import { SignatureLeadsToSelect } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/components/SignatureLeadsToSelect';
|
||||
|
||||
export const SignatureGroupContentWormholes = () => {
|
||||
return (
|
||||
<>
|
||||
<label className="grid grid-cols-[100px_250px_1fr] gap-2 items-center text-[14px]">
|
||||
<span>Type:</span>
|
||||
<SignatureWormholeTypeSelect name="type" />
|
||||
</label>
|
||||
|
||||
<label className="grid grid-cols-[100px_250px_1fr] gap-2 items-center text-[14px]">
|
||||
<span>Leads To:</span>
|
||||
<SignatureLeadsToSelect name="linked_system" />
|
||||
</label>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
import { Dropdown } from 'primereact/dropdown';
|
||||
import clsx from 'clsx';
|
||||
import { SignatureGroup, SystemSignature } from '@/hooks/Mapper/types';
|
||||
import { renderIcon } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/renders';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
|
||||
const signatureGroupOptions = Object.keys(SignatureGroup).map(x => ({
|
||||
value: SignatureGroup[x as keyof typeof SignatureGroup],
|
||||
label: SignatureGroup[x as keyof typeof SignatureGroup],
|
||||
}));
|
||||
|
||||
// @ts-ignore
|
||||
const renderSignatureTemplate = option => {
|
||||
if (!option) {
|
||||
return 'No group selected';
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex gap-2 items-center">
|
||||
<span className="w-[20px] mt-[1px] flex justify-center items-center">
|
||||
{renderIcon(
|
||||
{ group: option.label } as SystemSignature,
|
||||
option.label === SignatureGroup.CosmicSignature ? { w: 10, h: 10 } : { w: 16, h: 16 },
|
||||
)}
|
||||
</span>
|
||||
<span>{option.label}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export interface SignatureGroupSelectProps {
|
||||
name: string;
|
||||
defaultValue?: string;
|
||||
}
|
||||
|
||||
export const SignatureGroupSelect = ({ name, defaultValue = '' }: SignatureGroupSelectProps) => {
|
||||
const { control } = useFormContext();
|
||||
return (
|
||||
<Controller
|
||||
name={name}
|
||||
control={control}
|
||||
defaultValue={defaultValue}
|
||||
render={({ field }) => (
|
||||
<Dropdown
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
options={signatureGroupOptions}
|
||||
optionLabel="label"
|
||||
optionValue="value"
|
||||
placeholder="Select group"
|
||||
className={clsx('w-full')}
|
||||
scrollHeight="240px"
|
||||
itemTemplate={renderSignatureTemplate}
|
||||
valueTemplate={renderSignatureTemplate}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from './SignatureGroupSelect';
|
||||
@@ -0,0 +1,3 @@
|
||||
.SystemView {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
import { Dropdown } from 'primereact/dropdown';
|
||||
import clsx from 'clsx';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
import { useSystemsSettingsProvider } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/Provider.tsx';
|
||||
import { useSystemInfo } from '@/hooks/Mapper/components/hooks';
|
||||
import { useMemo } from 'react';
|
||||
import { SystemView } from '@/hooks/Mapper/components/ui-kit';
|
||||
import classes from './SignatureLeadsToSelect.module.scss';
|
||||
import { useLoadSystemStatic } from '@/hooks/Mapper/mapRootProvider/hooks/useLoadSystemStatic.ts';
|
||||
import { SystemSignature } from '@/hooks/Mapper/types';
|
||||
import { WORMHOLES_ADDITIONAL_INFO_BY_CLASS_ID } from '@/hooks/Mapper/components/map/constants.ts';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
|
||||
// @ts-ignore
|
||||
const renderLinkedSystemItem = (option: { value: string }) => {
|
||||
if (option.value == null) {
|
||||
return <div className="flex gap-2 items-center">No linked system</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex gap-2 items-center">
|
||||
<SystemView systemId={option.value} className={classes.SystemView} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
const renderLinkedSystemValue = (option: { value: string }) => {
|
||||
if (!option) {
|
||||
return 'Select Leads To system';
|
||||
}
|
||||
|
||||
if (option.value == null) {
|
||||
return 'Select Leads To system';
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex gap-2 items-center">
|
||||
<SystemView systemId={option.value} className={classes.SystemView} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const renderLeadsToEmpty = () => <div className="flex items-center text-[14px]">No wormhole to select</div>;
|
||||
|
||||
export interface SignatureLeadsToSelectProps {
|
||||
name: string;
|
||||
defaultValue?: string;
|
||||
}
|
||||
|
||||
export const SignatureLeadsToSelect = ({ name, defaultValue = '' }: SignatureLeadsToSelectProps) => {
|
||||
const { control, watch } = useFormContext<SystemSignature>();
|
||||
const group = watch('type');
|
||||
|
||||
const {
|
||||
value: { systemId },
|
||||
} = useSystemsSettingsProvider();
|
||||
|
||||
const { leadsTo } = useSystemInfo({ systemId });
|
||||
const { systems: systemStatics } = useLoadSystemStatic({ systems: leadsTo });
|
||||
const {
|
||||
data: { wormholes },
|
||||
} = useMapRootState();
|
||||
|
||||
const leadsToOptions = useMemo(() => {
|
||||
return [
|
||||
{ value: null },
|
||||
...leadsTo
|
||||
.filter(systemId => {
|
||||
const systemStatic = systemStatics.get(parseInt(systemId));
|
||||
const whInfo = wormholes.find(x => x.name === group);
|
||||
|
||||
if (!systemStatic || !whInfo || group === 'K162') {
|
||||
return true;
|
||||
}
|
||||
|
||||
const { id: whType } = WORMHOLES_ADDITIONAL_INFO_BY_CLASS_ID[systemStatic.system_class];
|
||||
return whInfo.dest === whType;
|
||||
})
|
||||
.map(x => ({ value: x })),
|
||||
];
|
||||
}, [group, leadsTo, systemStatics, wormholes]);
|
||||
|
||||
return (
|
||||
<Controller
|
||||
// @ts-ignore
|
||||
name={name}
|
||||
control={control}
|
||||
defaultValue={defaultValue}
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Dropdown
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
options={leadsToOptions}
|
||||
optionValue="value"
|
||||
placeholder="Select Leads To wormhole"
|
||||
className={clsx('w-full')}
|
||||
scrollHeight="240px"
|
||||
itemTemplate={renderLinkedSystemItem}
|
||||
valueTemplate={renderLinkedSystemValue}
|
||||
emptyMessage={renderLeadsToEmpty}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from './SignatureLeadsToSelect.tsx';
|
||||
@@ -0,0 +1,134 @@
|
||||
import { Dropdown } from 'primereact/dropdown';
|
||||
import clsx from 'clsx';
|
||||
import { Respawn, SolarSystemStaticInfoRaw, WormholeDataRaw } from '@/hooks/Mapper/types';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { useSystemsSettingsProvider } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/Provider.tsx';
|
||||
import { useSystemInfo } from '@/hooks/Mapper/components/hooks';
|
||||
import {
|
||||
SOLAR_SYSTEM_CLASSES_TO_CLASS_GROUPS,
|
||||
WORMHOLES_ADDITIONAL_INFO_BY_CLASS_ID,
|
||||
} from '@/hooks/Mapper/components/map/constants.ts';
|
||||
import { useMemo } from 'react';
|
||||
import { WHClassView } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
const getPossibleWormholes = (systemStatic: SolarSystemStaticInfoRaw, wormholes: WormholeDataRaw[]) => {
|
||||
const { id: whType } = WORMHOLES_ADDITIONAL_INFO_BY_CLASS_ID[systemStatic.system_class];
|
||||
|
||||
// @ts-ignore
|
||||
const spawnClassGroup = SOLAR_SYSTEM_CLASSES_TO_CLASS_GROUPS[whType];
|
||||
const possibleWHTypes = wormholes.filter(x => x.src.includes(spawnClassGroup));
|
||||
|
||||
return {
|
||||
statics: possibleWHTypes
|
||||
.filter(x => x.respawn.some(y => y === Respawn.static))
|
||||
.filter(x => systemStatic.statics.includes(x.name)),
|
||||
k162: wormholes.find(x => x.name === 'K162')!,
|
||||
wanderings: possibleWHTypes.filter(x => x.respawn.some(y => y === Respawn.wandering)),
|
||||
};
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
const renderWHTypeGroupTemplate = option => {
|
||||
return (
|
||||
<div className="flex gap-2 items-center">
|
||||
<span>{option.label}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
const renderWHTypeTemplateValue = (option: { label: string; data: WormholeDataRaw }) => {
|
||||
if (!option) {
|
||||
return 'Select wormhole type';
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex gap-2 items-center">
|
||||
<WHClassView whClassName={option.data.name} noOffset useShortTitle />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
const renderWHTypeTemplate = (option: { label: string; data: WormholeDataRaw }) => {
|
||||
return (
|
||||
<div className="flex gap-2 items-center ml-[1rem]">
|
||||
<WHClassView whClassName={option.data.name} noOffset useShortTitle />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export interface SignatureGroupSelectProps {
|
||||
name: string;
|
||||
defaultValue?: string;
|
||||
}
|
||||
|
||||
export const SignatureWormholeTypeSelect = ({ name, defaultValue = '' }: SignatureGroupSelectProps) => {
|
||||
const { control } = useFormContext();
|
||||
|
||||
const {
|
||||
data: { wormholes },
|
||||
} = useMapRootState();
|
||||
|
||||
const {
|
||||
value: { systemId },
|
||||
} = useSystemsSettingsProvider();
|
||||
|
||||
const system = useSystemInfo({ systemId });
|
||||
|
||||
const possibleWormholesOptions = useMemo(() => {
|
||||
const possibleWormholes = getPossibleWormholes(system.staticInfo, wormholes);
|
||||
|
||||
return [
|
||||
{
|
||||
label: 'Statics',
|
||||
items: [
|
||||
...possibleWormholes.statics.map(x => ({
|
||||
label: x.name,
|
||||
value: x.name,
|
||||
data: x,
|
||||
})),
|
||||
{
|
||||
value: possibleWormholes.k162.name,
|
||||
label: possibleWormholes.k162.name,
|
||||
data: possibleWormholes.k162,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Wanderings',
|
||||
items: possibleWormholes.wanderings.map(x => ({
|
||||
label: x.name,
|
||||
value: x.name,
|
||||
data: x,
|
||||
})),
|
||||
},
|
||||
];
|
||||
}, [system, wormholes]);
|
||||
|
||||
return (
|
||||
<Controller
|
||||
name={name}
|
||||
control={control}
|
||||
defaultValue={defaultValue}
|
||||
render={({ field }) => (
|
||||
<Dropdown
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
options={possibleWormholesOptions}
|
||||
optionLabel="label"
|
||||
optionValue="value"
|
||||
placeholder="Select wormhole type"
|
||||
optionGroupLabel="label"
|
||||
optionGroupChildren="items"
|
||||
className={clsx('w-full')}
|
||||
scrollHeight="240px"
|
||||
optionGroupTemplate={renderWHTypeGroupTemplate}
|
||||
itemTemplate={renderWHTypeTemplate}
|
||||
valueTemplate={renderWHTypeTemplateValue}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from './SignatureWormholeTypeSelect';
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './SignatureGroupSelect';
|
||||
export * from './SignatureGroupContent';
|
||||
@@ -0,0 +1 @@
|
||||
export * from './SignatureSettings.tsx';
|
||||
@@ -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)} />
|
||||
|
||||
@@ -37,7 +37,7 @@ export const CharacterCard = ({
|
||||
const { mapRef } = useMapRootState();
|
||||
|
||||
const handleSelect = useCallback(() => {
|
||||
mapRef.current?.command(Commands.selectSystem, char?.location?.solar_system_id?.toString());
|
||||
mapRef.current?.command(Commands.centerSystem, char?.location?.solar_system_id?.toString());
|
||||
}, [mapRef, char]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
.WHClassViewContent {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
|
||||
&.NoOffset {
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.WHClassName {
|
||||
@@ -13,3 +18,12 @@
|
||||
font-weight: bold;
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
.NoOffset {
|
||||
*.WHClassName {
|
||||
position: relative;
|
||||
font-size: 12px;
|
||||
font-weight: initial !important;
|
||||
top: initial !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,26 +16,42 @@ const prepareMass = (mass: number) => {
|
||||
|
||||
export interface WHClassViewProps {
|
||||
whClassName: string;
|
||||
noOffset?: boolean;
|
||||
useShortTitle?: boolean;
|
||||
hideWhClass?: boolean;
|
||||
highlightName?: boolean;
|
||||
className?: string;
|
||||
classNameWh?: string;
|
||||
}
|
||||
|
||||
export const WHClassView = ({ whClassName }: WHClassViewProps) => {
|
||||
export const WHClassView = ({
|
||||
whClassName,
|
||||
noOffset,
|
||||
useShortTitle,
|
||||
hideWhClass,
|
||||
highlightName,
|
||||
className,
|
||||
classNameWh,
|
||||
}: WHClassViewProps) => {
|
||||
const {
|
||||
data: { wormholesData },
|
||||
} = useMapRootState();
|
||||
|
||||
const whData = useMemo(() => wormholesData[whClassName], [whClassName, wormholesData]);
|
||||
const whClass = useMemo(() => WORMHOLES_ADDITIONAL_INFO[whData.dest], [whData.dest]);
|
||||
const whClassStyle = WORMHOLE_CLASS_STYLES[whClass.wormholeClassID];
|
||||
const whClassStyle = WORMHOLE_CLASS_STYLES[whClass?.wormholeClassID] ?? '';
|
||||
|
||||
const uid = useMemo(() => new Date().getTime().toString(), []);
|
||||
|
||||
return (
|
||||
<div className={classes.WHClassViewRoot}>
|
||||
<div className={clsx(classes.WHClassViewRoot, className)}>
|
||||
<Tooltip
|
||||
target={`.wh-name${whClassName}`}
|
||||
target={`.wh-name${whClassName}${uid}`}
|
||||
position="right"
|
||||
mouseTrack
|
||||
mouseTrackLeft={20}
|
||||
mouseTrackTop={30}
|
||||
className="border border-green-300 rounded border-opacity-10 bg-stone-900 bg-opacity-70 "
|
||||
className="border border-green-300 rounded border-opacity-10 bg-stone-900 bg-opacity-90 "
|
||||
>
|
||||
<div className="flex gap-3">
|
||||
<div className="flex flex-col gap-1">
|
||||
@@ -49,9 +65,20 @@ export const WHClassView = ({ whClassName }: WHClassViewProps) => {
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
||||
<div className={clsx(classes.WHClassViewContent, 'wh-name select-none cursor-help', `wh-name${whClassName}`)}>
|
||||
<span>{whClassName}</span>
|
||||
<span className={clsx(classes.WHClassName, whClassStyle)}>{whClass.shortName}</span>
|
||||
<div
|
||||
className={clsx(
|
||||
classes.WHClassViewContent,
|
||||
{ [classes.NoOffset]: noOffset },
|
||||
'wh-name select-none cursor-help',
|
||||
`wh-name${whClassName}${uid}`,
|
||||
)}
|
||||
>
|
||||
<span className={clsx({ [whClassStyle]: highlightName })}>{whClassName}</span>
|
||||
{!hideWhClass && whClass && (
|
||||
<span className={clsx(classes.WHClassName, whClassStyle, classNameWh)}>
|
||||
{useShortTitle ? whClass.shortTitle : whClass.shortName}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
12
assets/js/hooks/Mapper/events/index.ts
Normal file
12
assets/js/hooks/Mapper/events/index.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { createEvent } from 'react-event-hook';
|
||||
|
||||
import { Command, CommandData } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
|
||||
export interface MapEvent<T extends Command> {
|
||||
name: T;
|
||||
data: CommandData[T];
|
||||
}
|
||||
|
||||
const { useMapEventListener, emitMapEvent } = createEvent('map-event')<MapEvent<Command>>();
|
||||
|
||||
export { useMapEventListener, emitMapEvent };
|
||||
@@ -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[] => {
|
||||
@@ -19,6 +19,7 @@ export const parseSignatures = (value: string, availableKeys: string[]): SystemS
|
||||
kind: availableKeys.includes(sigArrInfo[1]) ? sigArrInfo[1] : COSMIC_SIGNATURE,
|
||||
group: sigArrInfo[2],
|
||||
name: sigArrInfo[3],
|
||||
type: '',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,10 @@ import { WORMHOLES_ADDITIONAL_INFO } from '@/hooks/Mapper/components/map/constan
|
||||
import { WormholeDataRaw } from '@/hooks/Mapper/types';
|
||||
|
||||
export const sortWHClasses = (wormholesData: Record<string, WormholeDataRaw>, statics: string[]) => {
|
||||
if (!statics) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return statics
|
||||
.map(x => wormholesData[x])
|
||||
.map(x => ({ name: x.name, ...WORMHOLES_ADDITIONAL_INFO[x.dest] }))
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './usePageVisibility';
|
||||
export * from './useClipboard';
|
||||
export * from './useHotkey';
|
||||
export * from './useSkipContextMenu';
|
||||
|
||||
15
assets/js/hooks/Mapper/hooks/useSkipContextMenu.ts
Normal file
15
assets/js/hooks/Mapper/hooks/useSkipContextMenu.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export const useSkipContextMenu = () => {
|
||||
useEffect(() => {
|
||||
function handleContextMenu(e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
window.addEventListener(`contextmenu`, handleContextMenu);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener(`contextmenu`, handleContextMenu);
|
||||
};
|
||||
}, []);
|
||||
};
|
||||
@@ -1,6 +1,5 @@
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import Mapper from './MapRoot';
|
||||
import { decompressToJson } from './utils';
|
||||
|
||||
export default {
|
||||
_rootEl: null,
|
||||
@@ -28,17 +27,12 @@ export default {
|
||||
|
||||
handleEventWrapper(event: string, handler: (payload: any) => void) {
|
||||
this.handleEvent(event, (body: any) => {
|
||||
if (event === 'map_event') {
|
||||
const { type, body: data } = body;
|
||||
handler({ type, body: decompressToJson(data) });
|
||||
} else {
|
||||
handler(body);
|
||||
}
|
||||
handler(body);
|
||||
});
|
||||
},
|
||||
|
||||
reconnected() {
|
||||
this.pushEvent('reconnected');
|
||||
this.pushEvent('ui_loaded');
|
||||
},
|
||||
|
||||
async pushEventAsync(event: string, payload: any) {
|
||||
|
||||
@@ -4,7 +4,6 @@ import { MapHandlers, MapUnionTypes, OutCommandHandler, SolarSystemConnection }
|
||||
import { useMapRootHandlers } from '@/hooks/Mapper/mapRootProvider/hooks';
|
||||
import { WithChildren } from '@/hooks/Mapper/types/common.ts';
|
||||
import useLocalStorageState from 'use-local-storage-state';
|
||||
import { DEFAULT_SETTINGS } from '@/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/RoutesProvider.tsx';
|
||||
|
||||
export type MapRootData = MapUnionTypes & {
|
||||
selectedSystems: string[];
|
||||
@@ -13,6 +12,7 @@ export type MapRootData = MapUnionTypes & {
|
||||
|
||||
const INITIAL_DATA: MapRootData = {
|
||||
wormholesData: {},
|
||||
wormholes: [],
|
||||
effects: {},
|
||||
characters: [],
|
||||
userCharacters: [],
|
||||
@@ -27,7 +27,13 @@ const INITIAL_DATA: MapRootData = {
|
||||
selectedConnections: [],
|
||||
};
|
||||
|
||||
type InterfaceStoredSettings = {
|
||||
export enum InterfaceStoredSettingsProps {
|
||||
isShowMenu = 'isShowMenu',
|
||||
isShowMinimap = 'isShowMinimap',
|
||||
isShowKSpace = 'isShowKSpace',
|
||||
}
|
||||
|
||||
export type InterfaceStoredSettings = {
|
||||
isShowMenu: boolean;
|
||||
isShowMinimap: boolean;
|
||||
isShowKSpace: boolean;
|
||||
|
||||
@@ -24,6 +24,7 @@ export const useMapInit = () => {
|
||||
|
||||
if (wormholes) {
|
||||
updateData.wormholesData = wormholes.reduce((acc, x) => ({ ...acc, [x.name]: x }), {});
|
||||
updateData.wormholes = wormholes;
|
||||
}
|
||||
|
||||
if (effects) {
|
||||
|
||||
@@ -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();
|
||||
@@ -47,15 +49,25 @@ export const useMapRootHandlers = (ref: ForwardedRef<MapHandlers>) => {
|
||||
break;
|
||||
case Commands.addSystems:
|
||||
addSystems(data as CommandAddSystems);
|
||||
setTimeout(() => {
|
||||
emitMapEvent({ name: Commands.addSystems, data });
|
||||
}, 100);
|
||||
break;
|
||||
case Commands.updateSystems:
|
||||
updateSystems(data as CommandUpdateSystems);
|
||||
break;
|
||||
case Commands.removeSystems:
|
||||
removeSystems(data as CommandRemoveSystems);
|
||||
setTimeout(() => {
|
||||
emitMapEvent({ name: Commands.removeSystems, data });
|
||||
}, 100);
|
||||
|
||||
break;
|
||||
case Commands.addConnections:
|
||||
addConnections(data as CommandAddConnections);
|
||||
setTimeout(() => {
|
||||
emitMapEvent({ name: Commands.addConnections, data });
|
||||
}, 100);
|
||||
break;
|
||||
case Commands.removeConnections:
|
||||
removeConnections(data as CommandRemoveConnections);
|
||||
@@ -85,14 +97,30 @@ export const useMapRootHandlers = (ref: ForwardedRef<MapHandlers>) => {
|
||||
mapRoutes(data as CommandRoutes);
|
||||
break;
|
||||
|
||||
case Commands.centerSystem:
|
||||
// do nothing here
|
||||
break;
|
||||
|
||||
case Commands.selectSystem:
|
||||
// do nothing here
|
||||
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;
|
||||
|
||||
default:
|
||||
console.warn(`JOipP Interface handlers: Unknown command: ${type}`, data);
|
||||
break;
|
||||
|
||||
@@ -21,7 +21,10 @@ export enum Commands {
|
||||
mapUpdated = 'map_updated',
|
||||
killsUpdated = 'kills_updated',
|
||||
routes = 'routes',
|
||||
centerSystem = 'center_system',
|
||||
selectSystem = 'select_system',
|
||||
linkSignatureToSystem = 'link_signature_to_system',
|
||||
signaturesUpdated = 'signatures_updated',
|
||||
}
|
||||
|
||||
export type Command =
|
||||
@@ -40,7 +43,10 @@ export type Command =
|
||||
| Commands.mapUpdated
|
||||
| Commands.killsUpdated
|
||||
| Commands.routes
|
||||
| Commands.selectSystem;
|
||||
| Commands.selectSystem
|
||||
| Commands.centerSystem
|
||||
| Commands.linkSignatureToSystem
|
||||
| Commands.signaturesUpdated;
|
||||
|
||||
export type CommandInit = {
|
||||
systems: SolarSystemRawType[];
|
||||
@@ -72,6 +78,12 @@ export type CommandMapUpdated = Partial<CommandInit>;
|
||||
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;
|
||||
};
|
||||
export type CommandLinkSignaturesUpdated = number;
|
||||
|
||||
export interface CommandData {
|
||||
[Commands.init]: CommandInit;
|
||||
@@ -90,6 +102,9 @@ export interface CommandData {
|
||||
[Commands.routes]: CommandRoutes;
|
||||
[Commands.killsUpdated]: CommandKillsUpdated;
|
||||
[Commands.selectSystem]: CommandSelectSystem;
|
||||
[Commands.centerSystem]: CommandCenterSystem;
|
||||
[Commands.linkSignatureToSystem]: CommandLinkSignatureToSystem;
|
||||
[Commands.signaturesUpdated]: CommandLinkSignaturesUpdated;
|
||||
}
|
||||
|
||||
export interface MapHandlers {
|
||||
@@ -107,6 +122,7 @@ export enum OutCommand {
|
||||
updateConnectionMassStatus = 'update_connection_mass_status',
|
||||
updateConnectionShipSizeType = 'update_connection_ship_size_type',
|
||||
updateConnectionLocked = 'update_connection_locked',
|
||||
updateConnectionCustomInfo = 'update_connection_custom_info',
|
||||
updateSignatures = 'update_signatures',
|
||||
updateSystemName = 'update_system_name',
|
||||
updateSystemDescription = 'update_system_description',
|
||||
@@ -123,10 +139,16 @@ export enum OutCommand {
|
||||
setAutopilotWaypoint = 'set_autopilot_waypoint',
|
||||
addSystem = 'add_system',
|
||||
addCharacter = 'add_character',
|
||||
openUserSettings = 'open_user_settings',
|
||||
getPassages = 'get_passages',
|
||||
linkSignatureToSystem = 'link_signature_to_system',
|
||||
|
||||
// Only UI commands
|
||||
openSettings = 'open_settings',
|
||||
|
||||
getUserSettings = 'get_user_settings',
|
||||
updateUserSettings = 'update_user_settings',
|
||||
unlinkSignature = 'unlink_signature',
|
||||
}
|
||||
|
||||
export type OutCommandHandler = <T = any>(event: { type: OutCommand; data: any }) => Promise<T>;
|
||||
|
||||
@@ -7,6 +7,7 @@ import { SolarSystemConnection } from '@/hooks/Mapper/types/connection.ts';
|
||||
|
||||
export type MapUnionTypes = {
|
||||
wormholesData: Record<string, WormholeDataRaw>;
|
||||
wormholes: WormholeDataRaw[];
|
||||
effects: Record<string, EffectRaw>;
|
||||
characters: CharacterTypeRaw[];
|
||||
userCharacters: string[];
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
export type SystemSignature = {
|
||||
eve_id: string;
|
||||
kind: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
group: string;
|
||||
updated_at?: string;
|
||||
};
|
||||
import { SolarSystemStaticInfoRaw } from '@/hooks/Mapper/types';
|
||||
|
||||
export enum SignatureGroup {
|
||||
CosmicSignature = 'Cosmic Signature',
|
||||
Wormhole = 'Wormhole',
|
||||
GasSite = 'Gas Site',
|
||||
RelicSite = 'Relic Site',
|
||||
DataSite = 'Data Site',
|
||||
OreSite = 'Ore Site',
|
||||
CombatSite = 'Combat Site',
|
||||
Wormhole = 'Wormhole',
|
||||
CosmicSignature = 'Cosmic Signature',
|
||||
}
|
||||
|
||||
export type GroupType = {
|
||||
@@ -23,3 +16,14 @@ export type GroupType = {
|
||||
w: number;
|
||||
h: number;
|
||||
};
|
||||
|
||||
export type SystemSignature = {
|
||||
eve_id: string;
|
||||
kind: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
group: SignatureGroup;
|
||||
type: string;
|
||||
linked_system?: SolarSystemStaticInfoRaw;
|
||||
updated_at?: string;
|
||||
};
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
export enum Respawn {
|
||||
static = 'static',
|
||||
wandering = 'wandering',
|
||||
reverse = 'reverse',
|
||||
}
|
||||
|
||||
export type WormholeDataRaw = {
|
||||
dest: string;
|
||||
id: number;
|
||||
@@ -5,7 +11,7 @@ export type WormholeDataRaw = {
|
||||
mass_regen: number;
|
||||
max_mass_per_jump: number;
|
||||
name: string;
|
||||
sibling_groups: any;
|
||||
respawn: Respawn[];
|
||||
src: string[];
|
||||
static: boolean;
|
||||
total_mass: number;
|
||||
|
||||
26
assets/js/hooks/Mapper/utils/abstractContextProvider.tsx
Normal file
26
assets/js/hooks/Mapper/utils/abstractContextProvider.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import { createContext, ReactNode, useContext, useState } from 'react';
|
||||
|
||||
type ContextType<T> = {
|
||||
value: T;
|
||||
setValue: (newValue: T) => void;
|
||||
};
|
||||
|
||||
export const createGenericContext = <T,>() => {
|
||||
const context = createContext<ContextType<T> | undefined>(undefined);
|
||||
|
||||
const Provider = ({ children, initialValue }: { children: ReactNode; initialValue: T }) => {
|
||||
const [value, setValue] = useState<T>(initialValue);
|
||||
|
||||
return <context.Provider value={{ value, setValue }}>{children}</context.Provider>;
|
||||
};
|
||||
|
||||
const useContextValue = () => {
|
||||
const contextValue = useContext(context);
|
||||
if (!contextValue) {
|
||||
throw new Error('useContextValue must be used within a Provider');
|
||||
}
|
||||
return contextValue;
|
||||
};
|
||||
|
||||
return { Provider, useContextValue };
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
import pako from 'pako';
|
||||
|
||||
export const decompressToJson = (base64string: string) => {
|
||||
const base64_decoded = atob(base64string);
|
||||
const charData = base64_decoded.split('').map(function (x) {
|
||||
return x.charCodeAt(0);
|
||||
});
|
||||
const zlibData = new Uint8Array(charData);
|
||||
const inflatedData = pako.inflate(zlibData, {
|
||||
to: 'string',
|
||||
});
|
||||
|
||||
return JSON.parse(inflatedData);
|
||||
};
|
||||
@@ -1,3 +1,2 @@
|
||||
export * from './contextStore';
|
||||
export * from './decompressToJson';
|
||||
export * from './getQueryVariable';
|
||||
|
||||
@@ -65,7 +65,7 @@ export class LabelsManager {
|
||||
}
|
||||
|
||||
hasLabel(label: string) {
|
||||
return this.parsedLabels.labels.includes(label);
|
||||
return this.parsedLabels.labels?.includes(label);
|
||||
}
|
||||
|
||||
toggleLabel(label: string) {
|
||||
|
||||
@@ -3,7 +3,230 @@ import 'phoenix_html';
|
||||
|
||||
import './live_reload.css';
|
||||
|
||||
const animateBg = function (bgCanvas) {
|
||||
const { TweenMax, _ } = window;
|
||||
/**
|
||||
* Utility function for returning a random integer in a given range
|
||||
* @param {Int} max
|
||||
* @param {Int} min
|
||||
*/
|
||||
const randomInRange = (max, min) => Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
const BASE_SIZE = 1;
|
||||
const VELOCITY_INC = 1.01;
|
||||
const VELOCITY_INIT_INC = 0.525;
|
||||
const JUMP_VELOCITY_INC = 0.55;
|
||||
const JUMP_SIZE_INC = 1.15;
|
||||
const SIZE_INC = 1.01;
|
||||
const RAD = Math.PI / 180;
|
||||
const WARP_COLORS = [
|
||||
[197, 239, 247],
|
||||
[25, 181, 254],
|
||||
[77, 5, 232],
|
||||
[165, 55, 253],
|
||||
[255, 255, 255],
|
||||
];
|
||||
/**
|
||||
* Class for storing the particle metadata
|
||||
* position, size, length, speed etc.
|
||||
*/
|
||||
class Star {
|
||||
STATE = {
|
||||
alpha: Math.random(),
|
||||
angle: randomInRange(0, 360) * RAD,
|
||||
};
|
||||
reset = () => {
|
||||
const angle = randomInRange(0, 360) * (Math.PI / 180);
|
||||
const vX = Math.cos(angle);
|
||||
const vY = Math.sin(angle);
|
||||
const travelled =
|
||||
Math.random() > 0.5
|
||||
? Math.random() * Math.max(window.innerWidth, window.innerHeight) + Math.random() * (window.innerWidth * 0.24)
|
||||
: Math.random() * (window.innerWidth * 0.25);
|
||||
this.STATE = {
|
||||
...this.STATE,
|
||||
iX: undefined,
|
||||
iY: undefined,
|
||||
active: travelled ? true : false,
|
||||
x: Math.floor(vX * travelled) + window.innerWidth / 2,
|
||||
vX,
|
||||
y: Math.floor(vY * travelled) + window.innerHeight / 2,
|
||||
vY,
|
||||
size: BASE_SIZE,
|
||||
};
|
||||
};
|
||||
constructor() {
|
||||
this.reset();
|
||||
}
|
||||
}
|
||||
|
||||
const generateStarPool = size => new Array(size).fill().map(() => new Star());
|
||||
|
||||
// Class for the actual app
|
||||
// Not too much happens in here
|
||||
// Initiate the drawing process and listen for user interactions 👍
|
||||
class JumpToHyperspace {
|
||||
STATE = {
|
||||
stars: generateStarPool(300),
|
||||
bgAlpha: 0,
|
||||
sizeInc: SIZE_INC,
|
||||
velocity: VELOCITY_INC,
|
||||
};
|
||||
canvas = null;
|
||||
context = null;
|
||||
constructor(canvas) {
|
||||
this.canvas = canvas;
|
||||
this.context = canvas.getContext('2d');
|
||||
this.bind();
|
||||
this.setup();
|
||||
this.render();
|
||||
}
|
||||
render = () => {
|
||||
const {
|
||||
STATE: { bgAlpha, velocity, sizeInc, initiating, jumping, stars },
|
||||
context,
|
||||
render,
|
||||
} = this;
|
||||
// Clear the canvas
|
||||
context.clearRect(0, 0, window.innerWidth, window.innerHeight);
|
||||
if (bgAlpha > 0) {
|
||||
context.fillStyle = `rgba(31, 58, 157, ${bgAlpha})`;
|
||||
context.fillRect(0, 0, window.innerWidth, window.innerHeight);
|
||||
}
|
||||
// 1. Shall we add a new star
|
||||
const nonActive = stars.filter(s => !s.STATE.active);
|
||||
if (!initiating && nonActive.length > 0) {
|
||||
// Introduce a star
|
||||
nonActive[0].STATE.active = true;
|
||||
}
|
||||
// 2. Update the stars and draw them.
|
||||
for (const star of stars.filter(s => s.STATE.active)) {
|
||||
const { active, x, y, iX, iY, iVX, iVY, size, vX, vY } = star.STATE;
|
||||
// Check if the star needs deactivating
|
||||
if (
|
||||
((iX || x) < 0 || (iX || x) > window.innerWidth || (iY || y) < 0 || (iY || y) > window.innerHeight) &&
|
||||
active &&
|
||||
!initiating
|
||||
) {
|
||||
star.reset(true);
|
||||
} else if (active) {
|
||||
const newIX = initiating ? iX : iX + iVX;
|
||||
const newIY = initiating ? iY : iY + iVY;
|
||||
const newX = x + vX;
|
||||
const newY = y + vY;
|
||||
// Just need to work out if it overtakes the original line that's all
|
||||
const caught =
|
||||
(vX < 0 && newIX < x) || (vX > 0 && newIX > x) || (vY < 0 && newIY < y) || (vY > 0 && newIY > y);
|
||||
star.STATE = {
|
||||
...star.STATE,
|
||||
iX: caught ? undefined : newIX,
|
||||
iY: caught ? undefined : newIY,
|
||||
iVX: caught ? undefined : iVX * VELOCITY_INIT_INC,
|
||||
iVY: caught ? undefined : iVY * VELOCITY_INIT_INC,
|
||||
x: newX,
|
||||
vX: star.STATE.vX * velocity,
|
||||
y: newY,
|
||||
vY: star.STATE.vY * velocity,
|
||||
size: initiating ? size : size * (iX || iY ? SIZE_INC : sizeInc),
|
||||
};
|
||||
let color = `rgba(255, 255, 255, ${star.STATE.alpha})`;
|
||||
if (jumping) {
|
||||
const [r, g, b] = WARP_COLORS[randomInRange(0, WARP_COLORS.length)];
|
||||
color = `rgba(${r}, ${g}, ${b}, ${star.STATE.alpha})`;
|
||||
}
|
||||
context.strokeStyle = color;
|
||||
context.lineWidth = size;
|
||||
context.beginPath();
|
||||
context.moveTo(star.STATE.iX || x, star.STATE.iY || y);
|
||||
context.lineTo(star.STATE.x, star.STATE.y);
|
||||
context.stroke();
|
||||
}
|
||||
}
|
||||
requestAnimationFrame(render);
|
||||
};
|
||||
initiate = () => {
|
||||
if (this.STATE.jumping || this.STATE.initiating) return;
|
||||
this.STATE = {
|
||||
...this.STATE,
|
||||
initiating: true,
|
||||
initiateTimestamp: new Date().getTime(),
|
||||
};
|
||||
TweenMax.to(this.STATE, 0.25, { velocity: VELOCITY_INIT_INC, bgAlpha: 0.3 });
|
||||
// When we initiate, stop the XY origin from moving so that we draw
|
||||
// longer lines until the jump
|
||||
for (const star of this.STATE.stars.filter(s => s.STATE.active)) {
|
||||
star.STATE = {
|
||||
...star.STATE,
|
||||
iX: star.STATE.x,
|
||||
iY: star.STATE.y,
|
||||
iVX: star.STATE.vX,
|
||||
iVY: star.STATE.vY,
|
||||
};
|
||||
}
|
||||
};
|
||||
jump = () => {
|
||||
this.STATE = {
|
||||
...this.STATE,
|
||||
bgAlpha: 0,
|
||||
jumping: true,
|
||||
};
|
||||
TweenMax.to(this.STATE, 0.25, { velocity: JUMP_VELOCITY_INC, bgAlpha: 0.75, sizeInc: JUMP_SIZE_INC });
|
||||
setTimeout(() => {
|
||||
this.STATE = {
|
||||
...this.STATE,
|
||||
jumping: false,
|
||||
};
|
||||
TweenMax.to(this.STATE, 0.25, { bgAlpha: 0, velocity: VELOCITY_INC, sizeInc: SIZE_INC });
|
||||
}, 5000);
|
||||
};
|
||||
enter = () => {
|
||||
if (this.STATE.jumping) return;
|
||||
const { initiateTimestamp } = this.STATE;
|
||||
this.STATE = {
|
||||
...this.STATE,
|
||||
initiating: false,
|
||||
initiateTimestamp: undefined,
|
||||
};
|
||||
if (new Date().getTime() - initiateTimestamp > 600) {
|
||||
this.jump();
|
||||
} else {
|
||||
TweenMax.to(this.STATE, 0.25, { velocity: VELOCITY_INC, bgAlpha: 0 });
|
||||
}
|
||||
};
|
||||
bind = () => {
|
||||
this.canvas.addEventListener('mousedown', this.initiate);
|
||||
this.canvas.addEventListener('touchstart', this.initiate);
|
||||
this.canvas.addEventListener('mouseup', this.enter);
|
||||
this.canvas.addEventListener('touchend', this.enter);
|
||||
};
|
||||
setup = () => {
|
||||
this.context.lineCap = 'round';
|
||||
this.canvas.height = window.innerHeight;
|
||||
this.canvas.width = window.innerWidth;
|
||||
};
|
||||
reset = () => {
|
||||
this.STATE = {
|
||||
...this.STATE,
|
||||
stars: generateStarPool(300),
|
||||
};
|
||||
this.setup();
|
||||
};
|
||||
}
|
||||
window.myJump = new JumpToHyperspace(bgCanvas);
|
||||
window.addEventListener(
|
||||
'resize',
|
||||
_.debounce(() => {
|
||||
window.myJump.reset();
|
||||
}, 250),
|
||||
);
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// animage background
|
||||
const canvas = document.getElementById('bg-canvas');
|
||||
if (canvas) {
|
||||
animateBg(canvas);
|
||||
}
|
||||
|
||||
// Select all buttons with the 'share-link' class
|
||||
const buttons = document.querySelectorAll('button.copy-link');
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
"live_select": "file:../deps/live_select",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"pako": "^2.1.0",
|
||||
"phoenix": "file:../deps/phoenix",
|
||||
"phoenix_html": "file:../deps/phoenix_html",
|
||||
"phoenix_live_view": "file:../deps/phoenix_live_view",
|
||||
@@ -29,8 +28,10 @@
|
||||
"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-hook-form": "^7.53.1",
|
||||
"react-usestateref": "^1.0.9",
|
||||
"reactflow": "^11.10.4",
|
||||
"rxjs": "^7.8.1",
|
||||
@@ -44,7 +45,6 @@
|
||||
"@tailwindcss/typography": "^0.5.13",
|
||||
"@types/lodash.debounce": "^4.0.9",
|
||||
"@types/lodash.isequal": "^4.5.8",
|
||||
"@types/pako": "^2.0.3",
|
||||
"@types/react": "18.2.0",
|
||||
"@types/react-dom": "18.2.1",
|
||||
"@types/react-grid-layout": "^1.3.4",
|
||||
|
||||
BIN
assets/static/images/amarr-180.png
Normal file
BIN
assets/static/images/amarr-180.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 187 KiB |
BIN
assets/static/images/caldaria-180.png
Normal file
BIN
assets/static/images/caldaria-180.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 109 KiB |
BIN
assets/static/images/gallente-180.png
Normal file
BIN
assets/static/images/gallente-180.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 205 KiB |
BIN
assets/static/images/mataria-180.png
Normal file
BIN
assets/static/images/mataria-180.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 262 KiB |
354
assets/yarn.lock
354
assets/yarn.lock
@@ -33,7 +33,7 @@
|
||||
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz"
|
||||
integrity sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==
|
||||
|
||||
"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.14.8", "@babel/core@^7.24.5":
|
||||
"@babel/core@^7.14.8", "@babel/core@^7.24.5":
|
||||
version "7.24.5"
|
||||
resolved "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz"
|
||||
integrity sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==
|
||||
@@ -240,11 +240,121 @@
|
||||
"@babel/helper-validator-identifier" "^7.24.5"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@esbuild/aix-ppc64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz#a70f4ac11c6a1dfc18b8bbb13284155d933b9537"
|
||||
integrity sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==
|
||||
|
||||
"@esbuild/android-arm64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz#db1c9202a5bc92ea04c7b6840f1bbe09ebf9e6b9"
|
||||
integrity sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==
|
||||
|
||||
"@esbuild/android-arm@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.2.tgz#3b488c49aee9d491c2c8f98a909b785870d6e995"
|
||||
integrity sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==
|
||||
|
||||
"@esbuild/android-x64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.2.tgz#3b1628029e5576249d2b2d766696e50768449f98"
|
||||
integrity sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==
|
||||
|
||||
"@esbuild/darwin-arm64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz"
|
||||
integrity sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==
|
||||
|
||||
"@esbuild/darwin-x64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz#90ed098e1f9dd8a9381695b207e1cff45540a0d0"
|
||||
integrity sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz#d71502d1ee89a1130327e890364666c760a2a911"
|
||||
integrity sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==
|
||||
|
||||
"@esbuild/freebsd-x64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz#aa5ea58d9c1dd9af688b8b6f63ef0d3d60cea53c"
|
||||
integrity sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==
|
||||
|
||||
"@esbuild/linux-arm64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz#055b63725df678379b0f6db9d0fa85463755b2e5"
|
||||
integrity sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==
|
||||
|
||||
"@esbuild/linux-arm@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz#76b3b98cb1f87936fbc37f073efabad49dcd889c"
|
||||
integrity sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==
|
||||
|
||||
"@esbuild/linux-ia32@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz#c0e5e787c285264e5dfc7a79f04b8b4eefdad7fa"
|
||||
integrity sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==
|
||||
|
||||
"@esbuild/linux-loong64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz#a6184e62bd7cdc63e0c0448b83801001653219c5"
|
||||
integrity sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==
|
||||
|
||||
"@esbuild/linux-mips64el@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz#d08e39ce86f45ef8fc88549d29c62b8acf5649aa"
|
||||
integrity sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==
|
||||
|
||||
"@esbuild/linux-ppc64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz#8d252f0b7756ffd6d1cbde5ea67ff8fd20437f20"
|
||||
integrity sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==
|
||||
|
||||
"@esbuild/linux-riscv64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz#19f6dcdb14409dae607f66ca1181dd4e9db81300"
|
||||
integrity sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==
|
||||
|
||||
"@esbuild/linux-s390x@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz#3c830c90f1a5d7dd1473d5595ea4ebb920988685"
|
||||
integrity sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==
|
||||
|
||||
"@esbuild/linux-x64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz#86eca35203afc0d9de0694c64ec0ab0a378f6fff"
|
||||
integrity sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==
|
||||
|
||||
"@esbuild/netbsd-x64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz#e771c8eb0e0f6e1877ffd4220036b98aed5915e6"
|
||||
integrity sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==
|
||||
|
||||
"@esbuild/openbsd-x64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz#9a795ae4b4e37e674f0f4d716f3e226dd7c39baf"
|
||||
integrity sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==
|
||||
|
||||
"@esbuild/sunos-x64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz#7df23b61a497b8ac189def6e25a95673caedb03f"
|
||||
integrity sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==
|
||||
|
||||
"@esbuild/win32-arm64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz#f1ae5abf9ca052ae11c1bc806fb4c0f519bacf90"
|
||||
integrity sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==
|
||||
|
||||
"@esbuild/win32-ia32@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz#241fe62c34d8e8461cd708277813e1d0ba55ce23"
|
||||
integrity sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==
|
||||
|
||||
"@esbuild/win32-x64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc"
|
||||
integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==
|
||||
|
||||
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
|
||||
version "4.4.0"
|
||||
resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz"
|
||||
@@ -341,7 +451,7 @@
|
||||
"@nodelib/fs.stat" "2.0.5"
|
||||
run-parallel "^1.1.9"
|
||||
|
||||
"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5":
|
||||
"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
|
||||
version "2.0.5"
|
||||
resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
|
||||
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
|
||||
@@ -359,7 +469,7 @@
|
||||
resolved "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz"
|
||||
integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==
|
||||
|
||||
"@react-rxjs/core@^0.10.7", "@react-rxjs/core@>=0.1.0":
|
||||
"@react-rxjs/core@^0.10.7":
|
||||
version "0.10.7"
|
||||
resolved "https://registry.npmjs.org/@react-rxjs/core/-/core-0.10.7.tgz"
|
||||
integrity sha512-dornp8pUs9OcdqFKKRh9+I2FVe21gWufNun6RYU1ddts7kUy9i4Thvl0iqcPFbGY61cJQMAJF7dxixWMSD/A/A==
|
||||
@@ -455,11 +565,91 @@
|
||||
estree-walker "^2.0.2"
|
||||
picomatch "^2.3.1"
|
||||
|
||||
"@rollup/rollup-android-arm-eabi@4.17.2":
|
||||
version "4.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz#1a32112822660ee104c5dd3a7c595e26100d4c2d"
|
||||
integrity sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==
|
||||
|
||||
"@rollup/rollup-android-arm64@4.17.2":
|
||||
version "4.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz#5aeef206d65ff4db423f3a93f71af91b28662c5b"
|
||||
integrity sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==
|
||||
|
||||
"@rollup/rollup-darwin-arm64@4.17.2":
|
||||
version "4.17.2"
|
||||
resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz"
|
||||
integrity sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==
|
||||
|
||||
"@rollup/rollup-darwin-x64@4.17.2":
|
||||
version "4.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz#f64fc51ed12b19f883131ccbcea59fc68cbd6c0b"
|
||||
integrity sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==
|
||||
|
||||
"@rollup/rollup-linux-arm-gnueabihf@4.17.2":
|
||||
version "4.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz#1a7641111be67c10111f7122d1e375d1226cbf14"
|
||||
integrity sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==
|
||||
|
||||
"@rollup/rollup-linux-arm-musleabihf@4.17.2":
|
||||
version "4.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.2.tgz#c93fd632923e0fee25aacd2ae414288d0b7455bb"
|
||||
integrity sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==
|
||||
|
||||
"@rollup/rollup-linux-arm64-gnu@4.17.2":
|
||||
version "4.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz#fa531425dd21d058a630947527b4612d9d0b4a4a"
|
||||
integrity sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==
|
||||
|
||||
"@rollup/rollup-linux-arm64-musl@4.17.2":
|
||||
version "4.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz#8acc16f095ceea5854caf7b07e73f7d1802ac5af"
|
||||
integrity sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==
|
||||
|
||||
"@rollup/rollup-linux-powerpc64le-gnu@4.17.2":
|
||||
version "4.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.2.tgz#94e69a8499b5cf368911b83a44bb230782aeb571"
|
||||
integrity sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==
|
||||
|
||||
"@rollup/rollup-linux-riscv64-gnu@4.17.2":
|
||||
version "4.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz#7ef1c781c7e59e85a6ce261cc95d7f1e0b56db0f"
|
||||
integrity sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==
|
||||
|
||||
"@rollup/rollup-linux-s390x-gnu@4.17.2":
|
||||
version "4.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.2.tgz#f15775841c3232fca9b78cd25a7a0512c694b354"
|
||||
integrity sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==
|
||||
|
||||
"@rollup/rollup-linux-x64-gnu@4.17.2":
|
||||
version "4.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz#b521d271798d037ad70c9f85dd97d25f8a52e811"
|
||||
integrity sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==
|
||||
|
||||
"@rollup/rollup-linux-x64-gnu@4.9.5":
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.5.tgz#85946ee4d068bd12197aeeec2c6f679c94978a49"
|
||||
integrity sha512-Dq1bqBdLaZ1Gb/l2e5/+o3B18+8TI9ANlA1SkejZqDgdU/jK/ThYaMPMJpVMMXy2uRHvGKbkz9vheVGdq3cJfA==
|
||||
|
||||
"@rollup/rollup-linux-x64-musl@4.17.2":
|
||||
version "4.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz#9254019cc4baac35800991315d133cc9fd1bf385"
|
||||
integrity sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==
|
||||
|
||||
"@rollup/rollup-win32-arm64-msvc@4.17.2":
|
||||
version "4.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz#27f65a89f6f52ee9426ec11e3571038e4671790f"
|
||||
integrity sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==
|
||||
|
||||
"@rollup/rollup-win32-ia32-msvc@4.17.2":
|
||||
version "4.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz#a2fbf8246ed0bb014f078ca34ae6b377a90cb411"
|
||||
integrity sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==
|
||||
|
||||
"@rollup/rollup-win32-x64-msvc@4.17.2":
|
||||
version "4.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz#5a2d08b81e8064b34242d5cc9973ef8dd1e60503"
|
||||
integrity sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==
|
||||
|
||||
"@rx-state/core@0.1.4":
|
||||
version "0.1.4"
|
||||
resolved "https://registry.npmjs.org/@rx-state/core/-/core-0.1.4.tgz"
|
||||
@@ -740,7 +930,7 @@
|
||||
"@types/d3-transition" "*"
|
||||
"@types/d3-zoom" "*"
|
||||
|
||||
"@types/estree@*", "@types/estree@^1.0.0", "@types/estree@1.0.5":
|
||||
"@types/estree@*", "@types/estree@1.0.5", "@types/estree@^1.0.0":
|
||||
version "1.0.5"
|
||||
resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz"
|
||||
integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
|
||||
@@ -774,11 +964,6 @@
|
||||
resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz"
|
||||
integrity sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==
|
||||
|
||||
"@types/pako@^2.0.3":
|
||||
version "2.0.3"
|
||||
resolved "https://registry.npmjs.org/@types/pako/-/pako-2.0.3.tgz"
|
||||
integrity sha512-bq0hMV9opAcrmE0Byyo0fY3Ew4tgOevJmQ9grUhpXQhYfyLJ1Kqg3P33JT5fdbT2AjeAjR51zqqVjAL/HMkx7Q==
|
||||
|
||||
"@types/prop-types@*":
|
||||
version "15.7.11"
|
||||
resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz"
|
||||
@@ -805,7 +990,7 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*", "@types/react@^17.0.0 || ^18.0.0", "@types/react@>=16.8", "@types/react@18.2.0":
|
||||
"@types/react@*", "@types/react@18.2.0":
|
||||
version "18.2.0"
|
||||
resolved "https://registry.npmjs.org/@types/react/-/react-18.2.0.tgz"
|
||||
integrity sha512-0FLj93y5USLHdnhIhABk83rm8XEGA7kH3cr+YUlvxoUGp1xNt/DINUMvqPxLyOQMzLmZe8i4RTHbvb8MC7NmrA==
|
||||
@@ -846,7 +1031,7 @@
|
||||
semver "^7.5.4"
|
||||
ts-api-utils "^1.0.1"
|
||||
|
||||
"@typescript-eslint/parser@^6.0.0 || ^6.0.0-alpha", "@typescript-eslint/parser@^6.21.0":
|
||||
"@typescript-eslint/parser@^6.21.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz"
|
||||
integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==
|
||||
@@ -947,7 +1132,7 @@ acorn-jsx@^5.3.2:
|
||||
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
|
||||
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
||||
|
||||
"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.4.0, acorn@^8.9.0:
|
||||
acorn@^8.4.0, acorn@^8.9.0:
|
||||
version "8.11.3"
|
||||
resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz"
|
||||
integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==
|
||||
@@ -1147,7 +1332,7 @@ braces@^3.0.2, braces@~3.0.2:
|
||||
dependencies:
|
||||
fill-range "^7.0.1"
|
||||
|
||||
browserslist@^4.22.2, browserslist@^4.23.0, "browserslist@>= 4.21.0":
|
||||
browserslist@^4.22.2, browserslist@^4.23.0:
|
||||
version "4.23.0"
|
||||
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz"
|
||||
integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==
|
||||
@@ -1205,7 +1390,7 @@ child_process@^1.0.2:
|
||||
resolved "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz"
|
||||
integrity sha512-Wmza/JzL0SiWz7kl6MhIKT5ceIlnFPJX+lwUGj7Clhy5MMldsSoJR0+uvRzOS5Kv45Mq7t1PoE8TsOA9bzvb6g==
|
||||
|
||||
chokidar@^3.3.0, chokidar@^3.5.3, "chokidar@>=3.0.0 <4.0.0":
|
||||
"chokidar@>=3.0.0 <4.0.0", chokidar@^3.3.0, chokidar@^3.5.3:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz"
|
||||
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
|
||||
@@ -1258,16 +1443,16 @@ color-convert@^2.0.1:
|
||||
dependencies:
|
||||
color-name "~1.1.4"
|
||||
|
||||
color-name@~1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
color-name@1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
|
||||
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
|
||||
|
||||
color-name@~1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
commander@^4.0.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz"
|
||||
@@ -1325,7 +1510,7 @@ culori@^3:
|
||||
resolved "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz"
|
||||
integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==
|
||||
|
||||
d3-drag@^3.0.0, "d3-drag@2 - 3":
|
||||
"d3-drag@2 - 3", d3-drag@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz"
|
||||
integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==
|
||||
@@ -1345,7 +1530,7 @@ d3-drag@^3.0.0, "d3-drag@2 - 3":
|
||||
dependencies:
|
||||
d3-color "1 - 3"
|
||||
|
||||
d3-selection@^3.0.0, "d3-selection@2 - 3", d3-selection@3:
|
||||
"d3-selection@2 - 3", d3-selection@3, d3-selection@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz"
|
||||
integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==
|
||||
@@ -1663,7 +1848,7 @@ escape-string-regexp@^4.0.0:
|
||||
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz"
|
||||
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
||||
|
||||
eslint-config-prettier@*, eslint-config-prettier@^9.1.0:
|
||||
eslint-config-prettier@^9.1.0:
|
||||
version "9.1.0"
|
||||
resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz"
|
||||
integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==
|
||||
@@ -1723,7 +1908,7 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4
|
||||
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz"
|
||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||
|
||||
"eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^7.0.0 || ^8.0.0", eslint@^8.57.0, eslint@>=7, eslint@>=7.0.0, eslint@>=8.0.0:
|
||||
eslint@^8.57.0:
|
||||
version "8.57.0"
|
||||
resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz"
|
||||
integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==
|
||||
@@ -1795,12 +1980,7 @@ estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0:
|
||||
resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz"
|
||||
integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
|
||||
|
||||
estree-walker@^2.0.1:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz"
|
||||
integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
|
||||
|
||||
estree-walker@^2.0.2:
|
||||
estree-walker@^2.0.1, estree-walker@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz"
|
||||
integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
|
||||
@@ -2010,18 +2190,6 @@ glob-parent@^6.0.2:
|
||||
dependencies:
|
||||
is-glob "^4.0.3"
|
||||
|
||||
glob@^7.1.3:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
|
||||
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.1.1"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@7.1.6:
|
||||
version "7.1.6"
|
||||
resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz"
|
||||
@@ -2034,6 +2202,18 @@ glob@7.1.6:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^7.1.3:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
|
||||
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.1.1"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
globals@^11.1.0:
|
||||
version "11.12.0"
|
||||
resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz"
|
||||
@@ -2141,14 +2321,7 @@ hasown@^2.0.0:
|
||||
dependencies:
|
||||
function-bind "^1.1.2"
|
||||
|
||||
hasown@^2.0.1:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz"
|
||||
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
|
||||
dependencies:
|
||||
function-bind "^1.1.2"
|
||||
|
||||
hasown@^2.0.2:
|
||||
hasown@^2.0.1, hasown@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz"
|
||||
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
|
||||
@@ -2420,7 +2593,7 @@ iterator.prototype@^1.1.2:
|
||||
reflect.getprototypeof "^1.0.4"
|
||||
set-function-name "^2.0.1"
|
||||
|
||||
jiti@^1.19.1, jiti@>=1.21.0:
|
||||
jiti@^1.19.1:
|
||||
version "1.21.0"
|
||||
resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz"
|
||||
integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==
|
||||
@@ -2518,7 +2691,6 @@ lines-and-columns@^1.1.6:
|
||||
|
||||
"live_select@file:../deps/live_select":
|
||||
version "1.4.2"
|
||||
resolved "file:../deps/live_select"
|
||||
|
||||
locate-path@^6.0.0:
|
||||
version "6.0.0"
|
||||
@@ -2612,13 +2784,6 @@ mini-svg-data-uri@^1.2.3:
|
||||
resolved "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz"
|
||||
integrity sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==
|
||||
|
||||
minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimatch@9.0.3:
|
||||
version "9.0.3"
|
||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz"
|
||||
@@ -2626,6 +2791,13 @@ minimatch@9.0.3:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
ms@2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
|
||||
@@ -2770,11 +2942,6 @@ p-locate@^5.0.0:
|
||||
dependencies:
|
||||
p-limit "^3.0.2"
|
||||
|
||||
pako@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz"
|
||||
integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==
|
||||
|
||||
parent-module@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz"
|
||||
@@ -2812,17 +2979,14 @@ path-type@^5.0.0:
|
||||
resolved "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz"
|
||||
integrity sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==
|
||||
|
||||
"phoenix@file:../deps/phoenix":
|
||||
version "1.7.14"
|
||||
|
||||
"phoenix_html@file:../deps/phoenix_html":
|
||||
version "4.1.0"
|
||||
resolved "file:../deps/phoenix_html"
|
||||
|
||||
"phoenix_live_view@file:../deps/phoenix_live_view":
|
||||
version "0.20.17"
|
||||
resolved "file:../deps/phoenix_live_view"
|
||||
|
||||
"phoenix@file:../deps/phoenix":
|
||||
version "1.7.14"
|
||||
resolved "file:../deps/phoenix"
|
||||
|
||||
picocolors@^1, picocolors@^1.0.0:
|
||||
version "1.0.0"
|
||||
@@ -2923,14 +3087,6 @@ postcss-reporter@^7.0.0:
|
||||
picocolors "^1.0.0"
|
||||
thenby "^1.3.4"
|
||||
|
||||
postcss-selector-parser@^6.0.11:
|
||||
version "6.0.13"
|
||||
resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz"
|
||||
integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==
|
||||
dependencies:
|
||||
cssesc "^3.0.0"
|
||||
util-deprecate "^1.0.2"
|
||||
|
||||
postcss-selector-parser@6.0.10:
|
||||
version "6.0.10"
|
||||
resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz"
|
||||
@@ -2939,12 +3095,20 @@ postcss-selector-parser@6.0.10:
|
||||
cssesc "^3.0.0"
|
||||
util-deprecate "^1.0.2"
|
||||
|
||||
postcss-selector-parser@^6.0.11:
|
||||
version "6.0.13"
|
||||
resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz"
|
||||
integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==
|
||||
dependencies:
|
||||
cssesc "^3.0.0"
|
||||
util-deprecate "^1.0.2"
|
||||
|
||||
postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz"
|
||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||
|
||||
postcss@^8.0.0, postcss@^8.1.0, postcss@^8.2.14, postcss@^8.4.21, postcss@^8.4.23, postcss@^8.4.38, postcss@>=8.0.9:
|
||||
postcss@^8.4.23, postcss@^8.4.38:
|
||||
version "8.4.38"
|
||||
resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz"
|
||||
integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==
|
||||
@@ -2965,7 +3129,7 @@ prettier-linter-helpers@^1.0.0:
|
||||
dependencies:
|
||||
fast-diff "^1.1.2"
|
||||
|
||||
prettier@^3.2.5, prettier@>=3.0.0:
|
||||
prettier@^3.2.5:
|
||||
version "3.2.5"
|
||||
resolved "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz"
|
||||
integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==
|
||||
@@ -2993,7 +3157,7 @@ primereact@^10.6.5:
|
||||
"@types/react-transition-group" "^4.4.1"
|
||||
react-transition-group "^4.4.1"
|
||||
|
||||
prop-types@^15.6.2, prop-types@^15.8.1, prop-types@15.x:
|
||||
prop-types@15.x, prop-types@^15.6.2, prop-types@^15.8.1:
|
||||
version "15.8.1"
|
||||
resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz"
|
||||
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
|
||||
@@ -3012,7 +3176,7 @@ queue-microtask@^1.2.2:
|
||||
resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz"
|
||||
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
|
||||
|
||||
"react-dom@^17.0.0 || ^18.0.0", "react-dom@>= 16.3.0", react-dom@>=16.6.0, react-dom@>=17, react-dom@>=18, "react-dom@16 || 17 || 18", react-dom@18.2.0:
|
||||
react-dom@18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz"
|
||||
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
|
||||
@@ -3035,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"
|
||||
@@ -3061,6 +3230,11 @@ react-grid-layout@^1.3.4:
|
||||
react-resizable "^3.0.5"
|
||||
resize-observer-polyfill "^1.5.1"
|
||||
|
||||
react-hook-form@^7.53.1:
|
||||
version "7.53.1"
|
||||
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.53.1.tgz#3f2cd1ed2b3af99416a4ac674da2d526625add67"
|
||||
integrity sha512-6aiQeBda4zjcuaugWvim9WsGqisoUk+etmFEsSUMm451/Ic8L/UAb7sRtMj3V+Hdzm6mMjU1VhiSzYUZeBm0Vg==
|
||||
|
||||
react-is@^16.13.1:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
|
||||
@@ -3099,7 +3273,7 @@ react-usestateref@^1.0.9:
|
||||
resolved "https://registry.npmjs.org/react-usestateref/-/react-usestateref-1.0.9.tgz"
|
||||
integrity sha512-t8KLsI7oje0HzfzGhxFXzuwbf1z9vhBM1ptHLUIHhYqZDKFuI5tzdhEVxSNzUkYxwF8XdpOErzHlKxvP7sTERw==
|
||||
|
||||
"react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^17.0.0 || ^18.0.0", react@^18.2.0, "react@>= 16.3", "react@>= 16.3.0", react@>=16.13.1, react@>=16.6.0, react@>=16.8, react@>=16.8.0, react@>=17, react@>=18, react@>16.0.0, "react@16 || 17 || 18", react@18.2.0:
|
||||
react@18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz"
|
||||
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
|
||||
@@ -3215,7 +3389,7 @@ rollup-plugin-external-globals@^0.10.0:
|
||||
is-reference "^3.0.2"
|
||||
magic-string "^0.30.5"
|
||||
|
||||
rollup@^1.20.0||^2.0.0||^3.0.0||^4.0.0, "rollup@^2.25.0 || ^3.3.0 || ^4.1.4", rollup@^4.13.0:
|
||||
rollup@^4.13.0:
|
||||
version "4.17.2"
|
||||
resolved "https://registry.npmjs.org/rollup/-/rollup-4.17.2.tgz"
|
||||
integrity sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==
|
||||
@@ -3247,7 +3421,7 @@ run-parallel@^1.1.9:
|
||||
dependencies:
|
||||
queue-microtask "^1.2.2"
|
||||
|
||||
rxjs@^7.8.1, rxjs@>=6, rxjs@>=7:
|
||||
rxjs@^7.8.1:
|
||||
version "7.8.1"
|
||||
resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz"
|
||||
integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==
|
||||
@@ -3280,7 +3454,7 @@ sass-loader@^14.2.1:
|
||||
dependencies:
|
||||
neo-async "^2.6.2"
|
||||
|
||||
sass@*, sass@^1.3.0, sass@^1.77.2:
|
||||
sass@^1.77.2:
|
||||
version "1.77.2"
|
||||
resolved "https://registry.npmjs.org/sass/-/sass-1.77.2.tgz"
|
||||
integrity sha512-eb4GZt1C3avsX3heBNlrc7I09nyT00IUuo4eFhAbeXWU2fvA7oXI53SxODVAA+zgZCk9aunAZgO+losjR3fAwA==
|
||||
@@ -3362,7 +3536,7 @@ slash@^5.0.0, slash@^5.1.0:
|
||||
resolved "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz"
|
||||
integrity sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==
|
||||
|
||||
source-map-js@^1.2.0, "source-map-js@>=0.6.2 <2.0.0":
|
||||
"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz"
|
||||
integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==
|
||||
@@ -3479,7 +3653,7 @@ synckit@^0.8.6:
|
||||
"@pkgr/core" "^0.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
tailwindcss@^3.3.6, "tailwindcss@>=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1", "tailwindcss@>=3.0.0 || >= 3.0.0-alpha.1", "tailwindcss@>=3.0.0 || insiders":
|
||||
tailwindcss@^3.3.6:
|
||||
version "3.3.6"
|
||||
resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.6.tgz"
|
||||
integrity sha512-AKjF7qbbLvLaPieoKeTjG1+FyNZT6KaJMJPFeQyLfIp7l82ggH1fbHJSsYIvnbTFQOlkh+gBYpyby5GT1LIdLw==
|
||||
@@ -3619,7 +3793,7 @@ typed-array-length@^1.0.6:
|
||||
is-typed-array "^1.1.13"
|
||||
possible-typed-array-names "^1.0.0"
|
||||
|
||||
typescript@^5.2.2, typescript@>=4.2.0:
|
||||
typescript@^5.2.2:
|
||||
version "5.4.5"
|
||||
resolved "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz"
|
||||
integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==
|
||||
@@ -3664,7 +3838,7 @@ use-local-storage-state@^19.3.1:
|
||||
resolved "https://registry.npmjs.org/use-local-storage-state/-/use-local-storage-state-19.3.1.tgz"
|
||||
integrity sha512-y3Z1dODXvZXZB4qtLDNN8iuXbsYD6TAxz61K58GWB9/yKwrNG9ynI0GzCTHi/Je1rMiyOwMimz0oyFsZn+Kj7Q==
|
||||
|
||||
use-sync-external-store@^1.0.0, use-sync-external-store@1.2.0:
|
||||
use-sync-external-store@1.2.0, use-sync-external-store@^1.0.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz"
|
||||
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
|
||||
@@ -3692,7 +3866,7 @@ vite-plugin-externals@^0.6.2:
|
||||
fs-extra "^10.0.0"
|
||||
magic-string "^0.25.7"
|
||||
|
||||
"vite@^4.2.0 || ^5.0.0", vite@^5.0.5, vite@>=2.0.0:
|
||||
vite@^5.0.5:
|
||||
version "5.2.11"
|
||||
resolved "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz"
|
||||
integrity sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==
|
||||
|
||||
@@ -60,15 +60,7 @@ config :dart_sass, :version, "1.54.5"
|
||||
|
||||
config :tailwind, :version, "3.2.7"
|
||||
|
||||
config :wanderer_app, WandererApp.PromEx,
|
||||
manual_metrics_start_delay: :no_delay,
|
||||
metrics_server: [
|
||||
port: 4021,
|
||||
path: "/metrics",
|
||||
protocol: :http,
|
||||
pool_size: 5,
|
||||
cowboy_opts: [ip: {0, 0, 0, 0}]
|
||||
]
|
||||
config :wanderer_app, WandererApp.PromEx, manual_metrics_start_delay: :no_delay
|
||||
|
||||
config :wanderer_app,
|
||||
grafana_datasource_id: "wanderer"
|
||||
|
||||
@@ -55,7 +55,6 @@ config :wanderer_app, WandererAppWeb.Endpoint,
|
||||
config :wanderer_app, WandererAppWeb.Endpoint,
|
||||
live_reload: [
|
||||
interval: 1000,
|
||||
web_console_logger: true,
|
||||
patterns: [
|
||||
~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$",
|
||||
~r"priv/gettext/.*(po)$",
|
||||
|
||||
@@ -77,7 +77,7 @@ config :wanderer_app,
|
||||
web_app_url: web_app_url,
|
||||
git_sha: System.get_env("GIT_SHA", "111"),
|
||||
custom_route_base_url: System.get_env("CUSTOM_ROUTE_BASE_URL"),
|
||||
invites: System.get_env("WANDERER_INVITES", "false") == "true",
|
||||
invites: System.get_env("WANDERER_INVITES", "false") |> String.to_existing_atom(),
|
||||
admin_username: System.get_env("WANDERER_ADMIN_USERNAME", "admin"),
|
||||
admin_password: System.get_env("WANDERER_ADMIN_PASSWORD"),
|
||||
admins: admins,
|
||||
|
||||
@@ -30,4 +30,19 @@ defmodule WandererApp do
|
||||
defmacro __using__(which) when is_atom(which) do
|
||||
apply(__MODULE__, which, [])
|
||||
end
|
||||
|
||||
def log_exception(kind, reason, stacktrace) do
|
||||
reason = Exception.normalize(kind, reason, stacktrace)
|
||||
|
||||
crash_reason =
|
||||
case kind do
|
||||
:throw -> {{:nocatch, reason}, stacktrace}
|
||||
_ -> {reason, stacktrace}
|
||||
end
|
||||
|
||||
Logger.error(
|
||||
Exception.format(kind, reason, stacktrace),
|
||||
crash_reason: crash_reason
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -19,6 +19,7 @@ defmodule WandererApp.Api do
|
||||
resource WandererApp.Api.MapCharacterSettings
|
||||
resource WandererApp.Api.MapSubscription
|
||||
resource WandererApp.Api.MapTransaction
|
||||
resource WandererApp.Api.MapUserSettings
|
||||
resource WandererApp.Api.User
|
||||
resource WandererApp.Api.ShipTypeInfo
|
||||
resource WandererApp.Api.UserActivity
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user