Initial commit

This commit is contained in:
Dmitry Popov
2024-09-18 01:55:30 +04:00
parent 6a96a5f56e
commit 4136aaad76
1675 changed files with 124664 additions and 1 deletions

View File

@@ -0,0 +1,15 @@
.ConnectionTimeEOL {
background-image: linear-gradient(207deg, transparent, #7452c3e3);
}
.ConnectionFrigate {
background-image: linear-gradient(207deg, transparent, #325d88);
}
.ConnectionSave {
background-image: linear-gradient(207deg, transparent, rgba(155, 102, 45, 0.85));
}
.SelectedItem {
background-color: rgba(98, 98, 98, 0.33);
}

View File

@@ -0,0 +1,95 @@
import React, { RefObject, useMemo } from 'react';
import { ContextMenu } from 'primereact/contextmenu';
import { PrimeIcons } from 'primereact/api';
import { MenuItem } from 'primereact/menuitem';
import { Edge } from '@reactflow/core/dist/esm/types/edges';
import { MassState, ShipSizeStatus, SolarSystemConnection, TimeStatus } from '@/hooks/Mapper/types';
import clsx from 'clsx';
import classes from './ContextMenuConnection.module.scss';
import { MASS_STATE_NAMES, MASS_STATE_NAMES_ORDER } from '@/hooks/Mapper/components/map/constants.ts';
export interface ContextMenuConnectionProps {
contextMenuRef: RefObject<ContextMenu>;
onDeleteConnection(): void;
onChangeTimeState(): void;
onChangeMassState(state: MassState): void;
onChangeShipSizeStatus(state: ShipSizeStatus): void;
onToggleMassSave(isLocked: boolean): void;
onHide(): void;
edge?: Edge<SolarSystemConnection>;
}
export const ContextMenuConnection: React.FC<ContextMenuConnectionProps> = ({
contextMenuRef,
onDeleteConnection,
onChangeTimeState,
onChangeMassState,
onChangeShipSizeStatus,
onToggleMassSave,
onHide,
edge,
}) => {
const items: MenuItem[] = useMemo(() => {
if (!edge) {
return [];
}
const isFrigateSize = edge.data?.ship_size_type === ShipSizeStatus.small;
return [
{
label: `EOL`,
className: clsx({
[classes.ConnectionTimeEOL]: edge.data?.time_status === TimeStatus.eol,
}),
icon: PrimeIcons.CLOCK,
command: onChangeTimeState,
},
{
label: `Frigate`,
className: clsx({
[classes.ConnectionFrigate]: isFrigateSize,
}),
icon: PrimeIcons.CLOUD,
command: () =>
onChangeShipSizeStatus(
edge.data?.ship_size_type === ShipSizeStatus.small ? ShipSizeStatus.normal : ShipSizeStatus.small,
),
},
{
label: `Save mass`,
className: clsx({
[classes.ConnectionSave]: edge.data?.locked,
}),
icon: PrimeIcons.LOCK,
command: () => onToggleMassSave(!edge.data?.locked),
},
...(!isFrigateSize
? [
{
label: `Mass status`,
icon: PrimeIcons.CHART_PIE,
items: MASS_STATE_NAMES_ORDER.map(x => ({
label: MASS_STATE_NAMES[x],
className: clsx({
[classes.SelectedItem]: edge.data?.mass_status === x,
}),
command: () => onChangeMassState(x),
})),
},
]
: []),
{
label: 'Disconnect',
icon: PrimeIcons.TRASH,
command: onDeleteConnection,
},
];
}, [edge, onChangeTimeState, onDeleteConnection, onChangeMassState, onChangeShipSizeStatus]);
return (
<>
<ContextMenu model={items} ref={contextMenuRef} onHide={onHide} breakpoint="767px" />
</>
);
};

View File

@@ -0,0 +1,2 @@
export * from './ContextMenuConnection.tsx';
export * from './useContextMenuConnectionHandlers.ts';

View File

@@ -0,0 +1,126 @@
import { EdgeMouseHandler } from 'reactflow';
import { useCallback, useRef, useState } from 'react';
import { ContextMenu } from 'primereact/contextmenu';
import { useMapState } from '../../MapProvider.tsx';
import { OutCommand } from '@/hooks/Mapper/types/mapHandlers.ts';
import { Edge } from '@reactflow/core/dist/esm/types/edges';
import { MassState, ShipSizeStatus, SolarSystemConnection, TimeStatus } from '@/hooks/Mapper/types';
import { ctxManager } from '@/hooks/Mapper/utils/contextManager.ts';
export const useContextMenuConnectionHandlers = () => {
const contextMenuRef = useRef<ContextMenu | null>(null);
const { outCommand } = useMapState();
const [edge, setEdge] = useState<Edge<SolarSystemConnection>>();
const ref = useRef({ edge, outCommand });
ref.current = { edge, outCommand };
const handleConnectionContext: EdgeMouseHandler = (ev, edge_) => {
setEdge(edge_);
ev.preventDefault();
ctxManager.next('ctxConn', contextMenuRef.current);
contextMenuRef.current?.show(ev);
};
const onDeleteConnection = () => {
if (!edge) {
return;
}
outCommand({ type: OutCommand.manualDeleteConnection, data: { source: edge.source, target: edge.target } });
setEdge(undefined);
};
const onChangeTimeState = () => {
if (!edge || !edge.data) {
return;
}
outCommand({
type: OutCommand.updateConnectionTimeStatus,
data: {
source: edge.source,
target: edge.target,
value: edge.data.time_status === TimeStatus.default ? TimeStatus.eol : TimeStatus.default,
},
});
setEdge(undefined);
};
const onChangeMassState = useCallback((status: MassState) => {
const { edge, outCommand } = ref.current;
if (!edge) {
return;
}
outCommand({
type: OutCommand.updateConnectionMassStatus,
data: {
source: edge.source,
target: edge.target,
value: status,
},
});
}, []);
const onChangeShipSizeStatus = useCallback((status: ShipSizeStatus) => {
const { edge, outCommand } = ref.current;
if (!edge) {
return;
}
outCommand({
type: OutCommand.updateConnectionShipSizeType,
data: {
source: edge.source,
target: edge.target,
value: status,
},
});
outCommand({
type: OutCommand.updateConnectionMassStatus,
data: {
source: edge.source,
target: edge.target,
value: MassState.normal,
},
});
}, []);
const onToggleMassSave = useCallback((locked: boolean) => {
const { edge, outCommand } = ref.current;
if (!edge) {
return;
}
outCommand({
type: OutCommand.updateConnectionLocked,
data: {
source: edge.source,
target: edge.target,
value: locked,
},
});
}, []);
const onHide = useCallback(() => {
setEdge(undefined);
}, []);
return {
handleConnectionContext,
edge,
contextMenuRef,
onDeleteConnection,
onChangeTimeState,
onChangeMassState,
onChangeShipSizeStatus,
onToggleMassSave,
onHide,
};
};