mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Completed advanced settings panel for tanker and AWACS
Reformatted files with larger width, reordered unused icons
This commit is contained in:
@@ -2,31 +2,21 @@ import React, { useEffect, useRef, useState } from "react";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faArrowCircleDown } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
export function OlAccordion(props: {
|
||||
title: string;
|
||||
children?: JSX.Element | JSX.Element[];
|
||||
showArrows?: boolean;
|
||||
}) {
|
||||
var [open, setOpen] = useState(false);
|
||||
var [scrolledUp, setScrolledUp] = useState(true);
|
||||
var [scrolledDown, setScrolledDown] = useState(false);
|
||||
export function OlAccordion(props: { title: string; children?: JSX.Element | JSX.Element[]; showArrows?: boolean }) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [scrolledUp, setScrolledUp] = useState(true);
|
||||
const [scrolledDown, setScrolledDown] = useState(false);
|
||||
|
||||
var contentRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
contentRef.current &&
|
||||
(contentRef.current as HTMLElement).children[0]?.addEventListener(
|
||||
"scroll",
|
||||
(e: any) => {
|
||||
if (e.target.clientHeight < e.target.scrollHeight) {
|
||||
setScrolledDown(
|
||||
e.target.scrollTop ===
|
||||
e.target.scrollHeight - e.target.offsetHeight
|
||||
);
|
||||
setScrolledUp(e.target.scrollTop === 0);
|
||||
}
|
||||
(contentRef.current as HTMLElement).children[0]?.addEventListener("scroll", (e: any) => {
|
||||
if (e.target.clientHeight < e.target.scrollHeight) {
|
||||
setScrolledDown(e.target.scrollTop === e.target.scrollHeight - e.target.offsetHeight);
|
||||
setScrolledUp(e.target.scrollTop === 0);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -61,13 +51,7 @@ export function OlAccordion(props: {
|
||||
fill="none"
|
||||
viewBox="0 0 10 6"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 5 5 1 1 5"
|
||||
/>
|
||||
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 5 5 1 1 5" />
|
||||
</svg>
|
||||
</button>
|
||||
</h3>
|
||||
|
||||
@@ -2,19 +2,11 @@ import { IconProp } from "@fortawesome/fontawesome-svg-core";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import React from "react";
|
||||
|
||||
export function OlButtonGroup(props: {
|
||||
children?: JSX.Element | JSX.Element[];
|
||||
}) {
|
||||
return (
|
||||
<div className="inline-flex rounded-md shadow-sm">{props.children}</div>
|
||||
);
|
||||
export function OlButtonGroup(props: { children?: JSX.Element | JSX.Element[] }) {
|
||||
return <div className="inline-flex rounded-md shadow-sm">{props.children}</div>;
|
||||
}
|
||||
|
||||
export function OlButtonGroupItem(props: {
|
||||
icon: IconProp;
|
||||
active: boolean;
|
||||
onClick: () => void;
|
||||
}) {
|
||||
export function OlButtonGroupItem(props: { icon: IconProp; active: boolean; onClick: () => void }) {
|
||||
return (
|
||||
<button
|
||||
onClick={props.onClick}
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
import React from "react";
|
||||
import {
|
||||
faSkull,
|
||||
faCamera,
|
||||
faFlag,
|
||||
faLink,
|
||||
faUnlink,
|
||||
faAngleDoubleRight,
|
||||
faExclamationCircle,
|
||||
faInfoCircle,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { faSkull, faCamera, faFlag, faLink, faUnlink, faAngleDoubleRight, faExclamationCircle, faInfoCircle } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
// Error message callout, only to be used for error messages
|
||||
@@ -21,12 +12,7 @@ export function ErrorCallout(props: { title?: string; description?: string }) {
|
||||
dark:bg-gray-800 dark:text-red-500
|
||||
`}
|
||||
>
|
||||
{props.title && (
|
||||
<FontAwesomeIcon
|
||||
className="mt-1"
|
||||
icon={faExclamationCircle}
|
||||
></FontAwesomeIcon>
|
||||
)}
|
||||
{props.title && <FontAwesomeIcon className="mt-1" icon={faExclamationCircle}></FontAwesomeIcon>}
|
||||
<div
|
||||
className={`
|
||||
flex flex-col content-center items-start gap-2 text-pretty font-bold
|
||||
@@ -55,9 +41,7 @@ export function InfoCallout(props: { title?: string; description?: string }) {
|
||||
dark:bg-gray-800 dark:text-blue-400
|
||||
`}
|
||||
>
|
||||
{props.title && (
|
||||
<FontAwesomeIcon className="mt-1" icon={faInfoCircle}></FontAwesomeIcon>
|
||||
)}
|
||||
{props.title && <FontAwesomeIcon className="mt-1" icon={faInfoCircle}></FontAwesomeIcon>}
|
||||
<div
|
||||
className={`
|
||||
flex flex-col content-center items-start gap-2 text-pretty font-medium
|
||||
@@ -88,10 +72,7 @@ export function CommandCallout(props: { coalition?: string }) {
|
||||
dark:bg-gray-800 dark:text-gray-400
|
||||
`}
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
className="mt-1"
|
||||
icon={faAngleDoubleRight}
|
||||
></FontAwesomeIcon>
|
||||
<FontAwesomeIcon className="mt-1" icon={faAngleDoubleRight}></FontAwesomeIcon>
|
||||
<div
|
||||
className={`
|
||||
content-center items-start gap-2 whitespace-break-spaces text-pretty
|
||||
@@ -100,13 +81,9 @@ export function CommandCallout(props: { coalition?: string }) {
|
||||
>
|
||||
You are playing as
|
||||
{props.coalition == "blue" ? (
|
||||
<div className="inline-block font-bold text-blue-500">
|
||||
BLUE COMMANDER
|
||||
</div>
|
||||
<div className="inline-block font-bold text-blue-500">BLUE COMMANDER</div>
|
||||
) : (
|
||||
<div className="inline-block font-bold text-red-500">
|
||||
RED COMMANDER
|
||||
</div>
|
||||
<div className="inline-block font-bold text-red-500">RED COMMANDER</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import React, { ChangeEvent } from "react";
|
||||
|
||||
export function OlCheckbox(props: {
|
||||
checked: boolean;
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
|
||||
}) {
|
||||
export function OlCheckbox(props: { checked: boolean; className?: string; disabled?: boolean; onChange: (e: ChangeEvent<HTMLInputElement>) => void }) {
|
||||
return (
|
||||
<input
|
||||
onChange={props.onChange}
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
import React from "react";
|
||||
import { Coalition } from "../../types/types";
|
||||
|
||||
export function OlCoalitionToggle(props: {
|
||||
coalition: Coalition | undefined;
|
||||
onClick: () => void;
|
||||
}) {
|
||||
export function OlCoalitionToggle(props: { coalition: Coalition | undefined; onClick: () => void }) {
|
||||
return (
|
||||
<div
|
||||
className="inline-flex cursor-pointer items-center"
|
||||
onClick={props.onClick}
|
||||
>
|
||||
<div className="inline-flex cursor-pointer items-center" onClick={props.onClick}>
|
||||
<button className="peer sr-only" />
|
||||
<div
|
||||
data-flash={props.coalition === undefined}
|
||||
@@ -39,9 +33,7 @@ export function OlCoalitionToggle(props: {
|
||||
data-[flash='true']:after:animate-pulse
|
||||
`}
|
||||
>
|
||||
{props.coalition
|
||||
? `${props.coalition[0].toLocaleUpperCase() + props.coalition.substring(1)}`
|
||||
: "Diff. values"}
|
||||
{props.coalition ? `${props.coalition[0].toLocaleUpperCase() + props.coalition.substring(1)}` : "Diff. values"}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -11,11 +11,9 @@ export function OlDropdown(props: {
|
||||
buttonRef?: MutableRefObject<null> | null;
|
||||
open?: boolean;
|
||||
}) {
|
||||
var [open, setOpen] =
|
||||
props.open !== undefined ? [props.open, () => {}] : useState(false);
|
||||
const [open, setOpen] = props.open !== undefined ? [props.open, () => {}] : useState(false);
|
||||
var contentRef = useRef(null);
|
||||
var buttonRef =
|
||||
props.buttonRef !== undefined ? props.buttonRef : useRef(null);
|
||||
var buttonRef = props.buttonRef !== undefined ? props.buttonRef : useRef(null);
|
||||
|
||||
function setPosition(content: HTMLDivElement, button: HTMLButtonElement) {
|
||||
/* Reset the position of the content */
|
||||
@@ -24,7 +22,7 @@ export function OlDropdown(props: {
|
||||
content.style.height = "";
|
||||
|
||||
/* Get the position and size of the button and the content elements */
|
||||
var [cxl, cyt, cxr, cyb, cw, ch] = [
|
||||
let [cxl, cyt, cxr, cyb, cw, ch] = [
|
||||
content.getBoundingClientRect().x,
|
||||
content.getBoundingClientRect().y,
|
||||
content.getBoundingClientRect().x + content.clientWidth,
|
||||
@@ -32,7 +30,7 @@ export function OlDropdown(props: {
|
||||
content.clientWidth,
|
||||
content.clientHeight,
|
||||
];
|
||||
var [bxl, byt, bxr, byb, bbw, bh] = [
|
||||
let [bxl, byt, bxr, byb, bbw, bh] = [
|
||||
button.getBoundingClientRect().x,
|
||||
button.getBoundingClientRect().y,
|
||||
button.getBoundingClientRect().x + button.clientWidth,
|
||||
@@ -81,11 +79,7 @@ export function OlDropdown(props: {
|
||||
/* Register click events to automatically close the dropdown when clicked anywhere outside of it */
|
||||
document.addEventListener("click", function (event) {
|
||||
const target = event.target;
|
||||
if (
|
||||
target &&
|
||||
!content.contains(target as HTMLElement) &&
|
||||
!button.contains(target as HTMLElement)
|
||||
) {
|
||||
if (target && !content.contains(target as HTMLElement) && !button.contains(target as HTMLElement)) {
|
||||
setOpen(false);
|
||||
}
|
||||
});
|
||||
@@ -93,9 +87,7 @@ export function OlDropdown(props: {
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
className={props.className ?? ""}
|
||||
>
|
||||
<div className={props.className ?? ""}>
|
||||
{props.buttonRef === undefined && (
|
||||
<button
|
||||
ref={buttonRef}
|
||||
@@ -111,12 +103,8 @@ export function OlDropdown(props: {
|
||||
`}
|
||||
type="button"
|
||||
>
|
||||
{props.leftIcon && (
|
||||
<FontAwesomeIcon icon={props.leftIcon} className={`mr-3`} />
|
||||
)}
|
||||
<span className="overflow-hidden text-ellipsis text-nowrap">
|
||||
{props.label ?? ""}
|
||||
</span>
|
||||
{props.leftIcon && <FontAwesomeIcon icon={props.leftIcon} className={`mr-3`} />}
|
||||
<span className="overflow-hidden text-ellipsis text-nowrap">{props.label ?? ""}</span>
|
||||
<svg
|
||||
className={`
|
||||
ml-auto ms-3 h-2.5 w-2.5 flex-none transition-transform
|
||||
@@ -127,13 +115,7 @@ export function OlDropdown(props: {
|
||||
fill="none"
|
||||
viewBox="0 0 10 6"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="m1 1 4 4 4-4"
|
||||
/>
|
||||
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="m1 1 4 4 4-4" />
|
||||
</svg>
|
||||
</button>
|
||||
)}
|
||||
@@ -142,7 +124,7 @@ export function OlDropdown(props: {
|
||||
ref={contentRef}
|
||||
data-open={open}
|
||||
className={`
|
||||
absolute divide-y divide-gray-100 overflow-y-scroll no-scrollbar
|
||||
absolute z-40 divide-y divide-gray-100 overflow-y-scroll no-scrollbar
|
||||
rounded-lg bg-white p-2 shadow
|
||||
dark:bg-gray-700
|
||||
data-[open='false']:hidden
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,18 +1,13 @@
|
||||
import React from "react";
|
||||
|
||||
export function OlLabelToggle(props: {
|
||||
toggled: boolean | undefined;
|
||||
leftLabel: string;
|
||||
rightLabel: string;
|
||||
onClick: () => void;
|
||||
}) {
|
||||
export function OlLabelToggle(props: { toggled: boolean | undefined; leftLabel: string; rightLabel: string; onClick: () => void }) {
|
||||
return (
|
||||
<button
|
||||
onClick={props.onClick}
|
||||
className={`
|
||||
relative flex h-10 w-[120px] flex-none cursor-pointer select-none
|
||||
flex-row justify-between rounded-md border px-1 py-[5px] text-sm
|
||||
contents-center
|
||||
flex-row content-center justify-between rounded-md border px-1 py-[5px]
|
||||
text-sm
|
||||
dark:border-gray-600 dark:border-transparent dark:bg-gray-700
|
||||
dark:hover:bg-gray-600 dark:focus:ring-blue-800
|
||||
focus:outline-none focus:ring-2 focus:ring-blue-300
|
||||
@@ -31,7 +26,7 @@ export function OlLabelToggle(props: {
|
||||
<span
|
||||
data-active={!(props.toggled ?? false)}
|
||||
className={`
|
||||
my-auto pl-3 font-normal transition-colors z-ui-1
|
||||
absolute left-[17px] top-[8px] font-normal transition-colors
|
||||
dark:data-[active='false']:text-gray-400
|
||||
dark:data-[active='true']:text-white
|
||||
`}
|
||||
@@ -41,7 +36,7 @@ export function OlLabelToggle(props: {
|
||||
<span
|
||||
data-active={props.toggled ?? false}
|
||||
className={`
|
||||
my-auto pr-3.5 font-normal transition-colors z-ui-1
|
||||
absolute right-[17px] top-[8px] font-normal transition-colors
|
||||
dark:data-[active='false']:text-gray-400
|
||||
dark:data-[active='true']:text-white
|
||||
`}
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
import React, { ChangeEvent, useEffect, useId } from "react";
|
||||
import React, { ChangeEvent } from "react";
|
||||
import { zeroAppend } from "../../other/utils";
|
||||
|
||||
export function OlNumberInput(props: {
|
||||
value: number;
|
||||
min: number;
|
||||
max: number;
|
||||
minLength?: number;
|
||||
className?: string;
|
||||
onDecrease: () => void;
|
||||
onIncrease: () => void;
|
||||
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="min-w-32">
|
||||
<div
|
||||
className={`
|
||||
${props.className ?? ""}
|
||||
min-w-32
|
||||
`}
|
||||
>
|
||||
<div className="relative flex max-w-[8rem] items-center">
|
||||
<button
|
||||
type="button"
|
||||
@@ -31,13 +39,7 @@ export function OlNumberInput(props: {
|
||||
fill="none"
|
||||
viewBox="0 0 18 2"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M1 1h16"
|
||||
/>
|
||||
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M1 1h16" />
|
||||
</svg>
|
||||
</button>
|
||||
<input
|
||||
@@ -53,7 +55,7 @@ export function OlNumberInput(props: {
|
||||
dark:focus:ring-blue-700
|
||||
focus:border-blue-700 focus:ring-blue-500
|
||||
`}
|
||||
value={props.value}
|
||||
value={zeroAppend(props.value, props.minLength ?? 0)}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
@@ -75,13 +77,7 @@ export function OlNumberInput(props: {
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 1v16M1 9h16" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -2,10 +2,7 @@ import { faMultiply, faSearch } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import React, { useId, useRef } from "react";
|
||||
|
||||
export function OlSearchBar(props: {
|
||||
onChange: (e: string) => void;
|
||||
text: string;
|
||||
}) {
|
||||
export function OlSearchBar(props: { onChange: (e: string) => void; text: string }) {
|
||||
const searchId = useId();
|
||||
const inputRef = useRef(null);
|
||||
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
import { IconProp } from "@fortawesome/fontawesome-svg-core";
|
||||
import {
|
||||
faExternalLink,
|
||||
faLock,
|
||||
faLockOpen,
|
||||
faUnlock,
|
||||
faUnlockAlt,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { faExternalLink, faLock, faLockOpen, faUnlock, faUnlockAlt } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import React, { useRef, useState } from "react";
|
||||
import { OlTooltip } from "./oltooltip";
|
||||
@@ -18,7 +12,7 @@ export function OlStateButton(props: {
|
||||
onClick: () => void;
|
||||
children?: JSX.Element | JSX.Element[];
|
||||
}) {
|
||||
var [hover, setHover] = useState(false);
|
||||
const [hover, setHover] = useState(false);
|
||||
var buttonRef = useRef(null);
|
||||
|
||||
const className =
|
||||
@@ -49,8 +43,8 @@ export function OlStateButton(props: {
|
||||
}}
|
||||
>
|
||||
<div className="m-auto flex w-fit content-center justify-center gap-2">
|
||||
<FontAwesomeIcon icon={props.icon} className="m-auto"/>
|
||||
{props.children}
|
||||
<FontAwesomeIcon icon={props.icon} className="m-auto" />
|
||||
{props.children}
|
||||
</div>
|
||||
</button>
|
||||
{hover && <OlTooltip buttonRef={buttonRef} content={props.tooltip} />}
|
||||
@@ -58,14 +52,8 @@ export function OlStateButton(props: {
|
||||
);
|
||||
}
|
||||
|
||||
export function OlRoundStateButton(props: {
|
||||
className?: string;
|
||||
checked: boolean;
|
||||
icon: IconProp;
|
||||
tooltip: string;
|
||||
onClick: () => void;
|
||||
}) {
|
||||
var [hover, setHover] = useState(false);
|
||||
export function OlRoundStateButton(props: { className?: string; checked: boolean; icon: IconProp; tooltip: string; onClick: () => void }) {
|
||||
const [hover, setHover] = useState(false);
|
||||
var buttonRef = useRef(null);
|
||||
|
||||
const className =
|
||||
@@ -106,13 +94,8 @@ export function OlRoundStateButton(props: {
|
||||
);
|
||||
}
|
||||
|
||||
export function OlLockStateButton(props: {
|
||||
className?: string;
|
||||
checked: boolean;
|
||||
tooltip: string;
|
||||
onClick: () => void;
|
||||
}) {
|
||||
var [hover, setHover] = useState(false);
|
||||
export function OlLockStateButton(props: { className?: string; checked: boolean; tooltip: string; onClick: () => void }) {
|
||||
const [hover, setHover] = useState(false);
|
||||
var buttonRef = useRef(null);
|
||||
|
||||
const className =
|
||||
@@ -143,10 +126,7 @@ export function OlLockStateButton(props: {
|
||||
setHover(false);
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
className="pt-[3px]"
|
||||
icon={props.checked == true ? faUnlockAlt : faLock}
|
||||
/>
|
||||
<FontAwesomeIcon className="pt-[3px]" icon={props.checked == true ? faUnlockAlt : faLock} />
|
||||
</button>
|
||||
{hover && <OlTooltip buttonRef={buttonRef} content={props.tooltip} />}
|
||||
</>
|
||||
|
||||
28
frontend/react/src/ui/components/olstringinput.tsx
Normal file
28
frontend/react/src/ui/components/olstringinput.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import React, { ChangeEvent } from "react";
|
||||
|
||||
export function OlStringInput(props: { value: string; className?: string; onChange: (e: ChangeEvent<HTMLInputElement>) => void }) {
|
||||
return (
|
||||
<div
|
||||
className={`
|
||||
${props.className ?? ""}
|
||||
min-w-32
|
||||
`}
|
||||
>
|
||||
<div className="relative flex max-w-[8rem] items-center">
|
||||
<input
|
||||
type="text"
|
||||
onChange={props.onChange}
|
||||
className={`
|
||||
block h-10 w-full rounded-md border-[2px] bg-gray-50 py-2.5
|
||||
text-center text-sm text-gray-900
|
||||
dark:border-gray-700 dark:bg-olympus-600 dark:text-white
|
||||
dark:placeholder-gray-400 dark:focus:border-blue-700
|
||||
dark:focus:ring-blue-700
|
||||
focus:border-blue-700 focus:ring-blue-500
|
||||
`}
|
||||
value={props.value}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,14 +1,8 @@
|
||||
import React from "react";
|
||||
|
||||
export function OlToggle(props: {
|
||||
toggled: boolean | undefined;
|
||||
onClick: () => void;
|
||||
}) {
|
||||
export function OlToggle(props: { toggled: boolean | undefined; onClick: () => void }) {
|
||||
return (
|
||||
<div
|
||||
className="inline-flex cursor-pointer items-center"
|
||||
onClick={props.onClick}
|
||||
>
|
||||
<div className="inline-flex cursor-pointer items-center" onClick={props.onClick}>
|
||||
<button className="peer sr-only" />
|
||||
<div
|
||||
data-flash={props.toggled === undefined}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
|
||||
export function OlTooltip(props: {
|
||||
content: string;
|
||||
buttonRef: React.MutableRefObject<null>;
|
||||
}) {
|
||||
export function OlTooltip(props: { content: string; buttonRef: React.MutableRefObject<null> }) {
|
||||
var contentRef = useRef(null);
|
||||
|
||||
function setPosition(content: HTMLDivElement, button: HTMLButtonElement) {
|
||||
@@ -13,7 +10,7 @@ export function OlTooltip(props: {
|
||||
content.style.height = "";
|
||||
|
||||
/* Get the position and size of the button and the content elements */
|
||||
var [cxl, cyt, cxr, cyb, cw, ch] = [
|
||||
let [cxl, cyt, cxr, cyb, cw, ch] = [
|
||||
content.getBoundingClientRect().x,
|
||||
content.getBoundingClientRect().y,
|
||||
content.getBoundingClientRect().x + content.clientWidth,
|
||||
@@ -21,7 +18,7 @@ export function OlTooltip(props: {
|
||||
content.clientWidth,
|
||||
content.clientHeight,
|
||||
];
|
||||
var [bxl, byt, bxr, byb, bbw, bh] = [
|
||||
let [bxl, byt, bxr, byb, bbw, bh] = [
|
||||
button.getBoundingClientRect().x,
|
||||
button.getBoundingClientRect().y,
|
||||
button.getBoundingClientRect().x + button.clientWidth,
|
||||
@@ -73,8 +70,8 @@ export function OlTooltip(props: {
|
||||
<div
|
||||
ref={contentRef}
|
||||
className={`
|
||||
absolute whitespace-nowrap z-ui-4 rounded-lg bg-gray-900 px-3 py-2
|
||||
text-sm font-medium text-white shadow-sm
|
||||
absolute whitespace-nowrap rounded-lg bg-gray-900 px-3 py-2 text-sm
|
||||
font-medium text-white shadow-sm
|
||||
dark:bg-gray-700
|
||||
`}
|
||||
>
|
||||
|
||||
@@ -2,19 +2,10 @@ import React from "react";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { IconProp } from "@fortawesome/fontawesome-svg-core";
|
||||
import { UnitBlueprint } from "../../interfaces";
|
||||
import {
|
||||
faArrowRightLong,
|
||||
faCaretRight,
|
||||
faCircleArrowRight,
|
||||
faLongArrowAltRight,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { faArrowRightLong, faCaretRight, faCircleArrowRight, faLongArrowAltRight } from "@fortawesome/free-solid-svg-icons";
|
||||
import { faArrowRight } from "@fortawesome/free-solid-svg-icons/faArrowRight";
|
||||
|
||||
export function OlUnitEntryList(props: {
|
||||
icon: IconProp;
|
||||
blueprint: UnitBlueprint;
|
||||
onClick: () => void;
|
||||
}) {
|
||||
export function OlUnitEntryList(props: { icon: IconProp; blueprint: UnitBlueprint; onClick: () => void }) {
|
||||
return (
|
||||
<div
|
||||
onClick={props.onClick}
|
||||
@@ -25,9 +16,7 @@ export function OlUnitEntryList(props: {
|
||||
`}
|
||||
>
|
||||
<FontAwesomeIcon icon={props.icon} className="text-sm"></FontAwesomeIcon>
|
||||
<div className="flex-1 px-2 text-left font-normal">
|
||||
{props.blueprint.label}
|
||||
</div>
|
||||
<div className="flex-1 px-2 text-left font-normal">{props.blueprint.label}</div>
|
||||
<div
|
||||
className={`
|
||||
rounded-full bg-olympus-800 px-2 py-0.5 text-xs font-bold
|
||||
|
||||
@@ -2,10 +2,7 @@ import React from "react";
|
||||
import { UnitBlueprint } from "../../interfaces";
|
||||
import { Coalition } from "../../types/types";
|
||||
|
||||
export function OlUnitSummary(props: {
|
||||
blueprint: UnitBlueprint;
|
||||
coalition: Coalition;
|
||||
}) {
|
||||
export function OlUnitSummary(props: { blueprint: UnitBlueprint; coalition: Coalition }) {
|
||||
return (
|
||||
<div
|
||||
data-coalition={props.coalition}
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
import React from "react";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import {
|
||||
faArrowRight,
|
||||
faCheckCircle,
|
||||
faExternalLink,
|
||||
faLink,
|
||||
faUnlink,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { faArrowRight, faCheckCircle, faExternalLink, faLink, faUnlink } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
export function Card(props: {
|
||||
children?: JSX.Element | JSX.Element[];
|
||||
className?: string;
|
||||
}) {
|
||||
export function Card(props: { children?: JSX.Element | JSX.Element[]; className?: string }) {
|
||||
return (
|
||||
<div
|
||||
className={`
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
import React from "react";
|
||||
|
||||
export function Modal(props: {
|
||||
grayout?: boolean;
|
||||
children?: JSX.Element | JSX.Element[];
|
||||
className?: string;
|
||||
}) {
|
||||
export function Modal(props: { grayout?: boolean; children?: JSX.Element | JSX.Element[]; className?: string }) {
|
||||
return (
|
||||
<div
|
||||
className={`
|
||||
${props.className}
|
||||
fixed left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] z-ui-4
|
||||
fixed left-[50%] top-[50%] z-40 translate-x-[-50%] translate-y-[-50%]
|
||||
rounded-xl border-[1px] border-solid border-gray-700 drop-shadow-md
|
||||
`}
|
||||
>
|
||||
|
||||
@@ -1,27 +1,10 @@
|
||||
import React, { useState, version } from "react";
|
||||
import React, { useState } from "react";
|
||||
import { Modal } from "./components/modal";
|
||||
import { Card } from "./components/card";
|
||||
import {
|
||||
ErrorCallout,
|
||||
InfoCallout,
|
||||
CommandCallout,
|
||||
} from "../../ui/components/olcallout";
|
||||
import { ErrorCallout } from "../../ui/components/olcallout";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import {
|
||||
faArrowRight,
|
||||
faCheckCircle,
|
||||
faDatabase,
|
||||
faExclamation,
|
||||
faExclamationCircle,
|
||||
faExternalLink,
|
||||
faLink,
|
||||
faServer,
|
||||
faSitemap,
|
||||
faUnlink,
|
||||
faWindowMaximize,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { VERSION, connectedToServer } from "../../olympusapp";
|
||||
import { faFirefoxBrowser } from "@fortawesome/free-brands-svg-icons";
|
||||
import { faArrowRight, faCheckCircle, faExternalLink } from "@fortawesome/free-solid-svg-icons";
|
||||
import { VERSION } from "../../olympusapp";
|
||||
|
||||
export function LoginModal(props: {
|
||||
checkingPassword: boolean;
|
||||
@@ -38,7 +21,7 @@ export function LoginModal(props: {
|
||||
<Modal
|
||||
className={`
|
||||
inline-flex h-[75%] max-h-[530px] w-[80%] max-w-[1100px] overflow-y-auto
|
||||
scroll-smooth bg-white z-ui-5
|
||||
scroll-smooth bg-white
|
||||
dark:bg-olympus-800
|
||||
max-md:h-full max-md:max-h-full max-md:w-full max-md:rounded-none
|
||||
max-md:border-none
|
||||
@@ -46,7 +29,9 @@ export function LoginModal(props: {
|
||||
>
|
||||
<img
|
||||
src="/vite/images/splash/1.jpg"
|
||||
className={`contents-center w-full object-cover opacity-[7%]`}
|
||||
className={`
|
||||
contents-center w-full object-cover opacity-[7%]
|
||||
`}
|
||||
></img>
|
||||
<div
|
||||
className={`
|
||||
@@ -107,7 +92,9 @@ export function LoginModal(props: {
|
||||
<span className="size-[80px] min-w-14">
|
||||
<img
|
||||
src="..\vite\images\olympus-500x500.png"
|
||||
className={`flex w-full`}
|
||||
className={`
|
||||
flex w-full
|
||||
`}
|
||||
></img>
|
||||
</span>
|
||||
<div className={`flex flex-col items-start gap-1`}>
|
||||
@@ -126,10 +113,7 @@ export function LoginModal(props: {
|
||||
dark:text-green-400
|
||||
`}
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={faCheckCircle}
|
||||
className={`my-auto`}
|
||||
/>
|
||||
<FontAwesomeIcon icon={faCheckCircle} className={`my-auto`} />
|
||||
Version {VERSION}
|
||||
</div>
|
||||
</div>
|
||||
@@ -149,9 +133,7 @@ export function LoginModal(props: {
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
onChange={(ev) =>
|
||||
setPassword(ev.currentTarget.value)
|
||||
}
|
||||
onChange={(ev) => setPassword(ev.currentTarget.value)}
|
||||
className={`
|
||||
block w-full max-w-80 rounded-lg border
|
||||
border-gray-300 bg-gray-50 p-2.5 text-sm
|
||||
@@ -182,10 +164,7 @@ export function LoginModal(props: {
|
||||
`}
|
||||
>
|
||||
Login
|
||||
<FontAwesomeIcon
|
||||
className={`my-auto`}
|
||||
icon={faArrowRight}
|
||||
/>
|
||||
<FontAwesomeIcon className={`my-auto`} icon={faArrowRight} />
|
||||
</button>
|
||||
{/*
|
||||
<button type="button" className="flex content-center items-center gap-2 text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium text-sm px-5 py-2.5 me-2 mb-2 dark:bg-gray-800 dark:hover:bg-gray-700 focus:outline-none dark:focus:ring-blue-800 rounded-sm dark:border-gray-600 border-[1px] dark:text-gray-400">
|
||||
@@ -213,9 +192,7 @@ export function LoginModal(props: {
|
||||
<input
|
||||
type="text"
|
||||
autoComplete="username"
|
||||
onChange={(ev) =>
|
||||
setDisplayName(ev.currentTarget.value)
|
||||
}
|
||||
onChange={(ev) => setDisplayName(ev.currentTarget.value)}
|
||||
className={`
|
||||
block w-full max-w-80 rounded-lg border
|
||||
border-gray-300 bg-gray-50 p-2.5 text-sm
|
||||
@@ -246,10 +223,7 @@ export function LoginModal(props: {
|
||||
`}
|
||||
>
|
||||
Continue
|
||||
<FontAwesomeIcon
|
||||
className={`my-auto`}
|
||||
icon={faArrowRight}
|
||||
/>
|
||||
<FontAwesomeIcon className={`my-auto`} icon={faArrowRight} />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
@@ -344,10 +318,7 @@ export function LoginModal(props: {
|
||||
`}
|
||||
>
|
||||
YouTube Video Guide
|
||||
<FontAwesomeIcon
|
||||
className={`my-auto text-xs text-gray-400`}
|
||||
icon={faExternalLink}
|
||||
/>
|
||||
<FontAwesomeIcon className={`my-auto text-xs text-gray-400`} icon={faExternalLink} />
|
||||
</div>
|
||||
<div
|
||||
className={`
|
||||
@@ -355,9 +326,7 @@ export function LoginModal(props: {
|
||||
dark:text-gray-400
|
||||
`}
|
||||
>
|
||||
Check out our official video tutorial on how to get started with
|
||||
Olympus - so you can immediately start controlling the
|
||||
battlefield.
|
||||
Check out our official video tutorial on how to get started with Olympus - so you can immediately start controlling the battlefield.
|
||||
</div>
|
||||
</Card>
|
||||
<Card className="flex">
|
||||
@@ -374,10 +343,7 @@ export function LoginModal(props: {
|
||||
`}
|
||||
>
|
||||
Wiki Guide
|
||||
<FontAwesomeIcon
|
||||
className={`my-auto text-xs text-gray-400`}
|
||||
icon={faExternalLink}
|
||||
/>
|
||||
<FontAwesomeIcon className={`my-auto text-xs text-gray-400`} icon={faExternalLink} />
|
||||
</div>
|
||||
<div
|
||||
className={`
|
||||
@@ -396,13 +362,9 @@ export function LoginModal(props: {
|
||||
max-lg:flex-col
|
||||
`}
|
||||
>
|
||||
DCS Olympus (the "MATERIAL" or "Software") is provided completely free
|
||||
to users subject to the terms of the CC BY-NC-SA 4.0 Licence except
|
||||
where such terms conflict with this disclaimer, in which case, the
|
||||
terms of this disclaimer shall prevail. Any party making use of the
|
||||
Software in any manner agrees to be bound by the terms set out in the
|
||||
disclaimer. THIS MATERIAL IS NOT MADE OR SUPPORTED BY EAGLE DYNAMICS
|
||||
SA.
|
||||
DCS Olympus (the "MATERIAL" or "Software") is provided completely free to users subject to the terms of the CC BY-NC-SA 4.0 Licence except where such
|
||||
terms conflict with this disclaimer, in which case, the terms of this disclaimer shall prevail. Any party making use of the Software in any manner
|
||||
agrees to be bound by the terms set out in the disclaimer. THIS MATERIAL IS NOT MADE OR SUPPORTED BY EAGLE DYNAMICS SA.
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
@@ -20,8 +20,8 @@ export function Menu(props: {
|
||||
<div
|
||||
data-open={props.open}
|
||||
className={`
|
||||
absolute left-16 right-0 top-[58px] bg-transparent z-ui-3
|
||||
pointer-events-none h-[calc(100vh-58px)] transition-transform
|
||||
pointer-events-none absolute left-16 right-0 top-[58px] z-10
|
||||
h-[calc(100vh-58px)] bg-transparent transition-transform
|
||||
data-[open='false']:-translate-x-full
|
||||
sm:w-[400px]
|
||||
`}
|
||||
@@ -71,7 +71,7 @@ export function Menu(props: {
|
||||
{props.canBeHidden == true && (
|
||||
<div
|
||||
className={`
|
||||
flex h-8 justify-center z-ui-4 pointer-events-auto backdrop-blur-lg
|
||||
pointer-events-auto flex h-8 justify-center backdrop-blur-lg
|
||||
backdrop-grayscale
|
||||
dark:bg-olympus-800/90
|
||||
`}
|
||||
@@ -80,7 +80,11 @@ export function Menu(props: {
|
||||
{hide ? (
|
||||
<FaChevronUp className="mx-auto my-auto text-gray-400" />
|
||||
) : (
|
||||
<FaChevronDown className="mx-auto my-auto text-gray-400" />
|
||||
<FaChevronDown
|
||||
className={`
|
||||
mx-auto my-auto text-gray-400
|
||||
`}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -24,8 +24,8 @@ export function ControlsPanel(props: {}) {
|
||||
return (
|
||||
<div
|
||||
className={`
|
||||
absolute bottom-[20px] right-[10px] w-80 z-ui-0 flex flex-col
|
||||
items-center justify-between gap-1 p-3 text-sm
|
||||
absolute bottom-[20px] right-[10px] flex w-80 flex-col items-center
|
||||
justify-between gap-1 p-3 text-sm
|
||||
`}
|
||||
>
|
||||
{controls.map((control) => {
|
||||
@@ -37,9 +37,7 @@ export function ControlsPanel(props: {}) {
|
||||
dark:bg-olympus-800/90 dark:text-gray-200
|
||||
`}
|
||||
>
|
||||
<div className="my-auto overflow-hidden text-nowrap">
|
||||
{control.text}
|
||||
</div>
|
||||
<div className="my-auto overflow-hidden text-nowrap">{control.text}</div>
|
||||
<div
|
||||
className={`
|
||||
ml-auto flex gap-1 rounded-full bg-olympus-500 px-2 py-0.5
|
||||
@@ -55,7 +53,9 @@ export function ControlsPanel(props: {}) {
|
||||
) : (
|
||||
<FontAwesomeIcon
|
||||
icon={action}
|
||||
className={`my-auto ml-auto`}
|
||||
className={`
|
||||
my-auto ml-auto
|
||||
`}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -2,12 +2,7 @@ import React, { useEffect, useState } from "react";
|
||||
import { Menu } from "./components/menu";
|
||||
import { FaQuestionCircle, FaRegCircle, FaTrash } from "react-icons/fa";
|
||||
import { getApp } from "../../olympusapp";
|
||||
import {
|
||||
COALITIONAREA_DRAW_CIRCLE,
|
||||
COALITIONAREA_DRAW_POLYGON,
|
||||
COALITIONAREA_EDIT,
|
||||
IDLE,
|
||||
} from "../../constants/constants";
|
||||
import { COALITIONAREA_DRAW_CIRCLE, COALITIONAREA_DRAW_POLYGON, COALITIONAREA_EDIT, IDLE } from "../../constants/constants";
|
||||
import { OlStateButton } from "../components/olstatebutton";
|
||||
import { faDrawPolygon } from "@fortawesome/free-solid-svg-icons";
|
||||
import { faCircle } from "@fortawesome/free-regular-svg-icons";
|
||||
@@ -22,14 +17,11 @@ import { CoalitionCircle } from "../../map/coalitionarea/coalitioncircle";
|
||||
export function DrawingMenu(props: { open: boolean; onClose: () => void }) {
|
||||
const [drawingPolygon, setDrawingPolygon] = useState(false);
|
||||
const [drawingCircle, setDrawingCircle] = useState(false);
|
||||
const [activeCoalitionArea, setActiveCoalitionArea] = useState(
|
||||
null as null | CoalitionPolygon | CoalitionCircle
|
||||
);
|
||||
const [activeCoalitionArea, setActiveCoalitionArea] = useState(null as null | CoalitionPolygon | CoalitionCircle);
|
||||
const [areaCoalition, setAreaCoalition] = useState("blue" as Coalition);
|
||||
const [IADSDensity, setIADSDensity] = useState(50);
|
||||
const [IADSDistribution, setIADSDistribution] = useState(50);
|
||||
const [forceCoalitionAppropriateUnits, setForceCoalitionApproriateUnits] =
|
||||
useState(false);
|
||||
const [forceCoalitionAppropriateUnits, setForceCoalitionApproriateUnits] = useState(false);
|
||||
|
||||
const [typesSelection, setTypesSelection] = useState({});
|
||||
const [erasSelection, setErasSelection] = useState({});
|
||||
@@ -37,55 +29,30 @@ export function DrawingMenu(props: { open: boolean; onClose: () => void }) {
|
||||
|
||||
useEffect(() => {
|
||||
/* If we are not in polygon drawing mode, force the draw polygon button off */
|
||||
if (
|
||||
drawingPolygon &&
|
||||
getApp().getMap().getState() !== COALITIONAREA_DRAW_POLYGON
|
||||
)
|
||||
setDrawingPolygon(false);
|
||||
if (drawingPolygon && getApp().getMap().getState() !== COALITIONAREA_DRAW_POLYGON) setDrawingPolygon(false);
|
||||
|
||||
/* If we are not in circle drawing mode, force the draw circle button off */
|
||||
if (
|
||||
drawingCircle &&
|
||||
getApp().getMap().getState() !== COALITIONAREA_DRAW_CIRCLE
|
||||
)
|
||||
setDrawingCircle(false);
|
||||
if (drawingCircle && getApp().getMap().getState() !== COALITIONAREA_DRAW_CIRCLE) setDrawingCircle(false);
|
||||
|
||||
/* If we are not in any drawing mode, force the map in edit mode */
|
||||
if (props.open && !drawingPolygon && !drawingCircle)
|
||||
getApp().getMap().setState(COALITIONAREA_EDIT);
|
||||
if (props.open && !drawingPolygon && !drawingCircle) getApp().getMap().setState(COALITIONAREA_EDIT);
|
||||
|
||||
/* Align the state of the coalition toggle to the coalition of the area */
|
||||
if (
|
||||
activeCoalitionArea &&
|
||||
activeCoalitionArea?.getCoalition() !== areaCoalition
|
||||
)
|
||||
setAreaCoalition(activeCoalitionArea?.getCoalition());
|
||||
if (activeCoalitionArea && activeCoalitionArea?.getCoalition() !== areaCoalition) setAreaCoalition(activeCoalitionArea?.getCoalition());
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.open) {
|
||||
if (
|
||||
[
|
||||
COALITIONAREA_EDIT,
|
||||
COALITIONAREA_DRAW_CIRCLE,
|
||||
COALITIONAREA_DRAW_POLYGON,
|
||||
].includes(getApp()?.getMap()?.getState())
|
||||
)
|
||||
if ([COALITIONAREA_EDIT, COALITIONAREA_DRAW_CIRCLE, COALITIONAREA_DRAW_POLYGON].includes(getApp()?.getMap()?.getState()))
|
||||
getApp().getMap().setState(IDLE);
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("mapStateChanged", (event: any) => {
|
||||
if (
|
||||
drawingPolygon &&
|
||||
getApp().getMap().getState() !== COALITIONAREA_DRAW_POLYGON
|
||||
)
|
||||
setDrawingPolygon(false);
|
||||
if (drawingPolygon && getApp().getMap().getState() !== COALITIONAREA_DRAW_POLYGON) setDrawingPolygon(false);
|
||||
|
||||
if (getApp().getMap().getState() == COALITIONAREA_EDIT) {
|
||||
setActiveCoalitionArea(
|
||||
getApp().getMap().getSelectedCoalitionArea() ?? null
|
||||
);
|
||||
setActiveCoalitionArea(getApp().getMap().getSelectedCoalitionArea() ?? null);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -109,21 +76,15 @@ export function DrawingMenu(props: { open: boolean; onClose: () => void }) {
|
||||
{activeCoalitionArea === null && !drawingPolygon && !drawingCircle && (
|
||||
<>
|
||||
<div className="p-4 text-sm text-gray-400">
|
||||
The draw tool allows you to quickly draw areas on the map and use
|
||||
these areas to spawn units and activate triggers.
|
||||
The draw tool allows you to quickly draw areas on the map and use these areas to spawn units and activate triggers.
|
||||
</div>
|
||||
<div className="mx-6 flex rounded-lg bg-olympus-400 p-4 text-sm">
|
||||
<div>
|
||||
<FaQuestionCircle className="my-4 ml-2 mr-6 text-gray-400" />
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="text-gray-100">
|
||||
Use the polygon or circle tool to draw areas on the map.
|
||||
</div>
|
||||
<div className="text-gray-400">
|
||||
After drawing a shape, select it to see the options for
|
||||
spawning units. Click on a shape to select it.
|
||||
</div>
|
||||
<div className="text-gray-100">Use the polygon or circle tool to draw areas on the map.</div>
|
||||
<div className="text-gray-400">After drawing a shape, select it to see the options for spawning units. Click on a shape to select it.</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
@@ -137,12 +98,9 @@ export function DrawingMenu(props: { open: boolean; onClose: () => void }) {
|
||||
<FaQuestionCircle className="my-4 ml-2 mr-6 text-gray-400" />
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="text-gray-100">
|
||||
Click on the map to add vertices to the polygon.
|
||||
</div>
|
||||
<div className="text-gray-100">Click on the map to add vertices to the polygon.</div>
|
||||
<div className="text-gray-400">
|
||||
When you are done, double click on the map to finalize the
|
||||
polygon. Vertices can be dragged or added to adjust the shape.
|
||||
When you are done, double click on the map to finalize the polygon. Vertices can be dragged or added to adjust the shape.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -156,13 +114,8 @@ export function DrawingMenu(props: { open: boolean; onClose: () => void }) {
|
||||
<FaQuestionCircle className="my-4 ml-2 mr-6 text-gray-400" />
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="text-gray-100">
|
||||
Click on the map to add a new circle.
|
||||
</div>
|
||||
<div className="text-gray-400">
|
||||
You can drag the circle to move it and you can use the handle to
|
||||
set the radius.
|
||||
</div>
|
||||
<div className="text-gray-100">Click on the map to add a new circle.</div>
|
||||
<div className="text-gray-400">You can drag the circle to move it and you can use the handle to set the radius.</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -177,8 +130,7 @@ export function DrawingMenu(props: { open: boolean; onClose: () => void }) {
|
||||
tooltip={"Add a new polygon"}
|
||||
checked={drawingPolygon}
|
||||
onClick={() => {
|
||||
if (drawingPolygon)
|
||||
getApp().getMap().setState(COALITIONAREA_EDIT);
|
||||
if (drawingPolygon) getApp().getMap().setState(COALITIONAREA_EDIT);
|
||||
else getApp().getMap().setState(COALITIONAREA_DRAW_POLYGON);
|
||||
setDrawingPolygon(!drawingPolygon);
|
||||
}}
|
||||
@@ -191,8 +143,7 @@ export function DrawingMenu(props: { open: boolean; onClose: () => void }) {
|
||||
tooltip={"Add a new circle"}
|
||||
checked={drawingCircle}
|
||||
onClick={() => {
|
||||
if (drawingCircle)
|
||||
getApp().getMap().setState(COALITIONAREA_EDIT);
|
||||
if (drawingCircle) getApp().getMap().setState(COALITIONAREA_EDIT);
|
||||
else getApp().getMap().setState(COALITIONAREA_DRAW_CIRCLE);
|
||||
setDrawingCircle(!drawingCircle);
|
||||
}}
|
||||
@@ -213,13 +164,14 @@ export function DrawingMenu(props: { open: boolean; onClose: () => void }) {
|
||||
>
|
||||
<div className="my-auto flex justify-between text-md">
|
||||
Area label
|
||||
<div className="rounded-md bg-red-800 p-2" onClick={() => {
|
||||
getApp().getMap().deleteCoalitionArea(activeCoalitionArea);
|
||||
setActiveCoalitionArea(null);
|
||||
}}>
|
||||
<FaTrash
|
||||
className={`text-gray-50`}
|
||||
></FaTrash>
|
||||
<div
|
||||
className="rounded-md bg-red-800 p-2"
|
||||
onClick={() => {
|
||||
getApp().getMap().deleteCoalitionArea(activeCoalitionArea);
|
||||
setActiveCoalitionArea(null);
|
||||
}}
|
||||
>
|
||||
<FaTrash className={`text-gray-50`}></FaTrash>
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
@@ -233,9 +185,7 @@ export function DrawingMenu(props: { open: boolean; onClose: () => void }) {
|
||||
focus:border-blue-500 focus:ring-blue-500
|
||||
`}
|
||||
placeholder={activeCoalitionArea.getLabelText()}
|
||||
onInput={(ev) =>
|
||||
activeCoalitionArea.setLabelText(ev.currentTarget.value)
|
||||
}
|
||||
onInput={(ev) => activeCoalitionArea.setLabelText(ev.currentTarget.value)}
|
||||
></input>
|
||||
</div>
|
||||
<div
|
||||
@@ -262,9 +212,7 @@ export function DrawingMenu(props: { open: boolean; onClose: () => void }) {
|
||||
bg-olympus-600 p-5
|
||||
`}
|
||||
>
|
||||
<div className="border-b-2 border-b-olympus-100 pb-4 text-gray-300">
|
||||
Automatic IADS generation
|
||||
</div>
|
||||
<div className="border-b-2 border-b-olympus-100 pb-4 text-gray-300">Automatic IADS generation</div>
|
||||
<OlDropdown className="" label="Units types">
|
||||
{getApp()
|
||||
.getGroundUnitDatabase()
|
||||
@@ -272,9 +220,7 @@ export function DrawingMenu(props: { open: boolean; onClose: () => void }) {
|
||||
.map((type) => {
|
||||
if (!(type in typesSelection)) {
|
||||
typesSelection[type] = true;
|
||||
setTypesSelection(
|
||||
JSON.parse(JSON.stringify(typesSelection))
|
||||
);
|
||||
setTypesSelection(JSON.parse(JSON.stringify(typesSelection)));
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -283,9 +229,7 @@ export function DrawingMenu(props: { open: boolean; onClose: () => void }) {
|
||||
checked={typesSelection[type]}
|
||||
onChange={(ev) => {
|
||||
typesSelection[type] = ev.currentTarget.checked;
|
||||
setTypesSelection(
|
||||
JSON.parse(JSON.stringify(typesSelection))
|
||||
);
|
||||
setTypesSelection(JSON.parse(JSON.stringify(typesSelection)));
|
||||
}}
|
||||
/>
|
||||
{type}
|
||||
@@ -300,9 +244,7 @@ export function DrawingMenu(props: { open: boolean; onClose: () => void }) {
|
||||
.map((era) => {
|
||||
if (!(era in erasSelection)) {
|
||||
erasSelection[era] = true;
|
||||
setErasSelection(
|
||||
JSON.parse(JSON.stringify(erasSelection))
|
||||
);
|
||||
setErasSelection(JSON.parse(JSON.stringify(erasSelection)));
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -311,9 +253,7 @@ export function DrawingMenu(props: { open: boolean; onClose: () => void }) {
|
||||
checked={erasSelection[era]}
|
||||
onChange={(ev) => {
|
||||
erasSelection[era] = ev.currentTarget.checked;
|
||||
setErasSelection(
|
||||
JSON.parse(JSON.stringify(erasSelection))
|
||||
);
|
||||
setErasSelection(JSON.parse(JSON.stringify(erasSelection)));
|
||||
}}
|
||||
/>
|
||||
{era}
|
||||
@@ -325,9 +265,7 @@ export function DrawingMenu(props: { open: boolean; onClose: () => void }) {
|
||||
{["Short range", "Medium range", "Long range"].map((range) => {
|
||||
if (!(range in rangesSelection)) {
|
||||
rangesSelection[range] = true;
|
||||
setRangesSelection(
|
||||
JSON.parse(JSON.stringify(rangesSelection))
|
||||
);
|
||||
setRangesSelection(JSON.parse(JSON.stringify(rangesSelection)));
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -336,9 +274,7 @@ export function DrawingMenu(props: { open: boolean; onClose: () => void }) {
|
||||
checked={rangesSelection[range]}
|
||||
onChange={(ev) => {
|
||||
rangesSelection[range] = ev.currentTarget.checked;
|
||||
setErasSelection(
|
||||
JSON.parse(JSON.stringify(rangesSelection))
|
||||
);
|
||||
setErasSelection(JSON.parse(JSON.stringify(rangesSelection)));
|
||||
}}
|
||||
/>
|
||||
{range}
|
||||
@@ -388,9 +324,7 @@ export function DrawingMenu(props: { open: boolean; onClose: () => void }) {
|
||||
<OlCheckbox
|
||||
checked={forceCoalitionAppropriateUnits}
|
||||
onChange={() => {
|
||||
setForceCoalitionApproriateUnits(
|
||||
!forceCoalitionAppropriateUnits
|
||||
);
|
||||
setForceCoalitionApproriateUnits(!forceCoalitionAppropriateUnits);
|
||||
}}
|
||||
/>
|
||||
Force coalition appropriate units
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
OlRoundStateButton,
|
||||
OlStateButton,
|
||||
OlLockStateButton,
|
||||
} from "../components/olstatebutton";
|
||||
import {
|
||||
faSkull,
|
||||
faCamera,
|
||||
faFlag,
|
||||
faLink,
|
||||
faUnlink,
|
||||
faBars,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { OlRoundStateButton, OlStateButton, OlLockStateButton } from "../components/olstatebutton";
|
||||
import { faSkull, faCamera, faFlag, faLink, faUnlink, faBars } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { EventsConsumer } from "../../eventscontext";
|
||||
import { StateConsumer } from "../../statecontext";
|
||||
@@ -61,20 +50,22 @@ export function Header() {
|
||||
{() => (
|
||||
<nav
|
||||
className={`
|
||||
flex w-full gap-4 border-gray-200 bg-gray-300 px-3
|
||||
drop-shadow-md z-ui-4 align-center
|
||||
z-10 flex w-full gap-4 border-gray-200 bg-gray-300 px-3
|
||||
drop-shadow-md align-center
|
||||
dark:border-gray-800 dark:bg-olympus-900
|
||||
`}
|
||||
>
|
||||
<img
|
||||
src="vite/images/icon.png"
|
||||
className="my-auto h-10 w-10 rounded-md p-0"
|
||||
className={`
|
||||
my-auto h-10 w-10 rounded-md p-0
|
||||
`}
|
||||
></img>
|
||||
{!scrolledLeft && (
|
||||
<FaChevronLeft
|
||||
className={`
|
||||
absolute left-14 h-full w-6 rounded-lg px-2 py-3.5
|
||||
text-gray-200 z-ui-1
|
||||
text-gray-200
|
||||
dark:bg-olympus-900
|
||||
`}
|
||||
/>
|
||||
@@ -124,11 +115,7 @@ export function Header() {
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<OlLockStateButton
|
||||
checked={false}
|
||||
onClick={() => {}}
|
||||
tooltip="Lock/unlock protected units (from scripted mission)"
|
||||
/>
|
||||
<OlLockStateButton checked={false} onClick={() => {}} tooltip="Lock/unlock protected units (from scripted mission)" />
|
||||
</div>
|
||||
<div className={`h-8 w-0 border-l-[2px] border-gray-700`}></div>
|
||||
<div
|
||||
@@ -145,12 +132,7 @@ export function Header() {
|
||||
<OlRoundStateButton
|
||||
key={entry[0]}
|
||||
onClick={() => {
|
||||
getApp()
|
||||
.getMap()
|
||||
.setHiddenType(
|
||||
entry[0],
|
||||
!appState.mapHiddenTypes[entry[0]]
|
||||
);
|
||||
getApp().getMap().setHiddenType(entry[0], !appState.mapHiddenTypes[entry[0]]);
|
||||
}}
|
||||
checked={!appState.mapHiddenTypes[entry[0]]}
|
||||
icon={entry[1]}
|
||||
@@ -166,36 +148,21 @@ export function Header() {
|
||||
`}
|
||||
>
|
||||
<OlRoundStateButton
|
||||
onClick={() =>
|
||||
getApp()
|
||||
.getMap()
|
||||
.setHiddenType("blue", !appState.mapHiddenTypes["blue"])
|
||||
}
|
||||
onClick={() => getApp().getMap().setHiddenType("blue", !appState.mapHiddenTypes["blue"])}
|
||||
checked={!appState.mapHiddenTypes["blue"]}
|
||||
icon={faFlag}
|
||||
className={"!text-blue-500"}
|
||||
tooltip={"Hide/show blue units"}
|
||||
/>
|
||||
<OlRoundStateButton
|
||||
onClick={() =>
|
||||
getApp()
|
||||
.getMap()
|
||||
.setHiddenType("red", !appState.mapHiddenTypes["red"])
|
||||
}
|
||||
onClick={() => getApp().getMap().setHiddenType("red", !appState.mapHiddenTypes["red"])}
|
||||
checked={!appState.mapHiddenTypes["red"]}
|
||||
icon={faFlag}
|
||||
className={"!text-red-500"}
|
||||
tooltip={"Hide/show red units"}
|
||||
/>
|
||||
<OlRoundStateButton
|
||||
onClick={() =>
|
||||
getApp()
|
||||
.getMap()
|
||||
.setHiddenType(
|
||||
"neutral",
|
||||
!appState.mapHiddenTypes["neutral"]
|
||||
)
|
||||
}
|
||||
onClick={() => getApp().getMap().setHiddenType("neutral", !appState.mapHiddenTypes["neutral"])}
|
||||
checked={!appState.mapHiddenTypes["neutral"]}
|
||||
icon={faFlag}
|
||||
className={"!text-gray-500"}
|
||||
@@ -221,12 +188,7 @@ export function Header() {
|
||||
<OlRoundStateButton
|
||||
key={entry[0]}
|
||||
onClick={() => {
|
||||
getApp()
|
||||
.getMap()
|
||||
.setHiddenType(
|
||||
entry[0],
|
||||
!appState.mapHiddenTypes[entry[0]]
|
||||
);
|
||||
getApp().getMap().setHiddenType(entry[0], !appState.mapHiddenTypes[entry[0]]);
|
||||
}}
|
||||
checked={!appState.mapHiddenTypes[entry[0]]}
|
||||
icon={entry[1]}
|
||||
@@ -236,25 +198,12 @@ export function Header() {
|
||||
})}
|
||||
</div>
|
||||
|
||||
<OlLabelToggle
|
||||
toggled={false}
|
||||
leftLabel={"Live"}
|
||||
rightLabel={"Map"}
|
||||
onClick={() => {}}
|
||||
></OlLabelToggle>
|
||||
<OlStateButton
|
||||
checked={false}
|
||||
icon={faCamera}
|
||||
onClick={() => {}}
|
||||
tooltip="Activate/deactivate camera plugin"
|
||||
/>
|
||||
<OlLabelToggle toggled={false} leftLabel={"Live"} rightLabel={"Map"} onClick={() => {}}></OlLabelToggle>
|
||||
<OlStateButton checked={false} icon={faCamera} onClick={() => {}} tooltip="Activate/deactivate camera plugin" />
|
||||
<OlDropdown label={appState.activeMapSource} className="w-60">
|
||||
{appState.mapSources.map((source) => {
|
||||
return (
|
||||
<OlDropdownItem
|
||||
key={source}
|
||||
onClick={() => getApp().getMap().setLayerName(source)}
|
||||
>
|
||||
<OlDropdownItem key={source} onClick={() => getApp().getMap().setLayerName(source)}>
|
||||
<div className="truncate">{source}</div>
|
||||
</OlDropdownItem>
|
||||
);
|
||||
@@ -265,7 +214,7 @@ export function Header() {
|
||||
<FaChevronRight
|
||||
className={`
|
||||
absolute right-0 h-full w-6 rounded-lg px-2 py-3.5
|
||||
text-gray-200 z-ui-1
|
||||
text-gray-200
|
||||
dark:bg-olympus-900
|
||||
`}
|
||||
/>
|
||||
|
||||
@@ -16,18 +16,9 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { VERSION } from "../../olympusapp";
|
||||
import { faGithub } from "@fortawesome/free-brands-svg-icons";
|
||||
|
||||
export function MainMenu(props: {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
children?: JSX.Element | JSX.Element[];
|
||||
}) {
|
||||
export function MainMenu(props: { open: boolean; onClose: () => void; children?: JSX.Element | JSX.Element[] }) {
|
||||
return (
|
||||
<Menu
|
||||
title="Main Menu"
|
||||
open={props.open}
|
||||
showBackButton={false}
|
||||
onClose={props.onClose}
|
||||
>
|
||||
<Menu title="Main Menu" open={props.open} showBackButton={false} onClose={props.onClose}>
|
||||
<div
|
||||
className={`
|
||||
flex flex-col gap-1 p-5 font-normal text-gray-900
|
||||
@@ -45,10 +36,7 @@ export function MainMenu(props: {
|
||||
<FontAwesomeIcon icon={faCheckCircle} className={`my-auto`} />
|
||||
Olympus Version {VERSION}
|
||||
</div>
|
||||
<div className="text-sm text-gray-400">
|
||||
You can use the Olympus Manager to update port, passwords or other
|
||||
settings.
|
||||
</div>
|
||||
<div className="text-sm text-gray-400">You can use the Olympus Manager to update port, passwords or other settings.</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
|
||||
@@ -5,18 +5,18 @@ import { getApp } from "../../olympusapp";
|
||||
import { FaChevronDown, FaChevronUp } from "react-icons/fa6";
|
||||
|
||||
export function MiniMapPanel(props: {}) {
|
||||
var [frameRate, setFrameRate] = useState(0);
|
||||
var [load, setLoad] = useState(0);
|
||||
var [elapsedTime, setElapsedTime] = useState(0);
|
||||
var [missionTime, setMissionTime] = useState({
|
||||
const [frameRate, setFrameRate] = useState(0);
|
||||
const [load, setLoad] = useState(0);
|
||||
const [elapsedTime, setElapsedTime] = useState(0);
|
||||
const [missionTime, setMissionTime] = useState({
|
||||
h: 0,
|
||||
m: 0,
|
||||
s: 0,
|
||||
} as DateAndTime["time"]);
|
||||
var [connected, setConnected] = useState(false);
|
||||
var [paused, setPaused] = useState(false);
|
||||
var [showMissionTime, setShowMissionTime] = useState(false);
|
||||
var [showMinimap, setShowMinimap] = useState(false);
|
||||
const [connected, setConnected] = useState(false);
|
||||
const [paused, setPaused] = useState(false);
|
||||
const [showMissionTime, setShowMissionTime] = useState(false);
|
||||
const [showMinimap, setShowMinimap] = useState(false);
|
||||
|
||||
document.addEventListener("serverStatusUpdated", (ev) => {
|
||||
const detail = (ev as CustomEvent).detail;
|
||||
@@ -73,7 +73,7 @@ export function MiniMapPanel(props: {}) {
|
||||
className={`
|
||||
absolute right-[10px]
|
||||
${showMinimap ? `top-[232px]` : `top-[70px]`}
|
||||
w-[288px] z-ui-0 flex items-center justify-between
|
||||
flex w-[288px] items-center justify-between
|
||||
${showMinimap ? `rounded-b-lg` : `rounded-lg`}
|
||||
bg-gray-200 p-3 text-sm backdrop-blur-lg backdrop-grayscale
|
||||
dark:bg-olympus-800/90 dark:text-gray-200
|
||||
|
||||
@@ -6,19 +6,9 @@ import { OlNumberInput } from "../components/olnumberinput";
|
||||
import { MapOptions } from "../../types/types";
|
||||
import { getApp } from "../../olympusapp";
|
||||
|
||||
export function Options(props: {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
options: MapOptions;
|
||||
children?: JSX.Element | JSX.Element[];
|
||||
}) {
|
||||
export function Options(props: { open: boolean; onClose: () => void; options: MapOptions; children?: JSX.Element | JSX.Element[] }) {
|
||||
return (
|
||||
<Menu
|
||||
title="User preferences"
|
||||
open={props.open}
|
||||
showBackButton={false}
|
||||
onClose={props.onClose}
|
||||
>
|
||||
<Menu title="User preferences" open={props.open} showBackButton={false} onClose={props.onClose}>
|
||||
<div
|
||||
className={`
|
||||
flex flex-col gap-2 p-5 font-normal text-gray-800
|
||||
@@ -32,15 +22,10 @@ export function Options(props: {
|
||||
dark:hover:bg-olympus-400
|
||||
`}
|
||||
onClick={() => {
|
||||
getApp()
|
||||
.getMap()
|
||||
.setOption("showUnitLabels", !props.options.showUnitLabels);
|
||||
getApp().getMap().setOption("showUnitLabels", !props.options.showUnitLabels);
|
||||
}}
|
||||
>
|
||||
<OlCheckbox
|
||||
checked={props.options.showUnitLabels}
|
||||
onChange={() => {}}
|
||||
></OlCheckbox>
|
||||
<OlCheckbox checked={props.options.showUnitLabels} onChange={() => {}}></OlCheckbox>
|
||||
<span>Show Unit Labels</span>
|
||||
<kbd
|
||||
className={`
|
||||
@@ -59,18 +44,10 @@ export function Options(props: {
|
||||
dark:hover:bg-olympus-400
|
||||
`}
|
||||
onClick={() => {
|
||||
getApp()
|
||||
.getMap()
|
||||
.setOption(
|
||||
"showUnitsEngagementRings",
|
||||
!props.options.showUnitsEngagementRings
|
||||
);
|
||||
getApp().getMap().setOption("showUnitsEngagementRings", !props.options.showUnitsEngagementRings);
|
||||
}}
|
||||
>
|
||||
<OlCheckbox
|
||||
checked={props.options.showUnitsEngagementRings}
|
||||
onChange={() => {}}
|
||||
></OlCheckbox>
|
||||
<OlCheckbox checked={props.options.showUnitsEngagementRings} onChange={() => {}}></OlCheckbox>
|
||||
<span>Show Threat Rings</span>
|
||||
<kbd
|
||||
className={`
|
||||
@@ -89,18 +66,10 @@ export function Options(props: {
|
||||
dark:hover:bg-olympus-400
|
||||
`}
|
||||
onClick={() => {
|
||||
getApp()
|
||||
.getMap()
|
||||
.setOption(
|
||||
"showUnitsAcquisitionRings",
|
||||
!props.options.showUnitsAcquisitionRings
|
||||
);
|
||||
getApp().getMap().setOption("showUnitsAcquisitionRings", !props.options.showUnitsAcquisitionRings);
|
||||
}}
|
||||
>
|
||||
<OlCheckbox
|
||||
checked={props.options.showUnitsAcquisitionRings}
|
||||
onChange={() => {}}
|
||||
></OlCheckbox>
|
||||
<OlCheckbox checked={props.options.showUnitsAcquisitionRings} onChange={() => {}}></OlCheckbox>
|
||||
<span>Show Detection rings</span>
|
||||
<kbd
|
||||
className={`
|
||||
@@ -119,15 +88,10 @@ export function Options(props: {
|
||||
dark:hover:bg-olympus-400
|
||||
`}
|
||||
onClick={() => {
|
||||
getApp()
|
||||
.getMap()
|
||||
.setOption("showUnitTargets", !props.options.showUnitTargets);
|
||||
getApp().getMap().setOption("showUnitTargets", !props.options.showUnitTargets);
|
||||
}}
|
||||
>
|
||||
<OlCheckbox
|
||||
checked={props.options.showUnitTargets}
|
||||
onChange={() => {}}
|
||||
></OlCheckbox>
|
||||
<OlCheckbox checked={props.options.showUnitTargets} onChange={() => {}}></OlCheckbox>
|
||||
<span>Show Detection lines</span>
|
||||
<kbd
|
||||
className={`
|
||||
@@ -146,18 +110,10 @@ export function Options(props: {
|
||||
dark:hover:bg-olympus-400
|
||||
`}
|
||||
onClick={() => {
|
||||
getApp()
|
||||
.getMap()
|
||||
.setOption(
|
||||
"hideUnitsShortRangeRings",
|
||||
!props.options.hideUnitsShortRangeRings
|
||||
);
|
||||
getApp().getMap().setOption("hideUnitsShortRangeRings", !props.options.hideUnitsShortRangeRings);
|
||||
}}
|
||||
>
|
||||
<OlCheckbox
|
||||
checked={props.options.hideUnitsShortRangeRings}
|
||||
onChange={() => {}}
|
||||
></OlCheckbox>
|
||||
<OlCheckbox checked={props.options.hideUnitsShortRangeRings} onChange={() => {}}></OlCheckbox>
|
||||
<span>Hide Short range Rings</span>
|
||||
<kbd
|
||||
className={`
|
||||
@@ -176,15 +132,10 @@ export function Options(props: {
|
||||
dark:hover:bg-olympus-400
|
||||
`}
|
||||
onClick={() => {
|
||||
getApp()
|
||||
.getMap()
|
||||
.setOption("hideGroupMembers", !props.options.hideGroupMembers);
|
||||
getApp().getMap().setOption("hideGroupMembers", !props.options.hideGroupMembers);
|
||||
}}
|
||||
>
|
||||
<OlCheckbox
|
||||
checked={props.options.hideGroupMembers}
|
||||
onChange={() => {}}
|
||||
></OlCheckbox>
|
||||
<OlCheckbox checked={props.options.hideGroupMembers} onChange={() => {}}></OlCheckbox>
|
||||
<span>Hide Group members</span>
|
||||
<kbd
|
||||
className={`
|
||||
@@ -203,15 +154,10 @@ export function Options(props: {
|
||||
dark:hover:bg-olympus-400
|
||||
`}
|
||||
onClick={() => {
|
||||
getApp()
|
||||
.getMap()
|
||||
.setOption("showMinimap", !props.options.showMinimap);
|
||||
getApp().getMap().setOption("showMinimap", !props.options.showMinimap);
|
||||
}}
|
||||
>
|
||||
<OlCheckbox
|
||||
checked={props.options.showMinimap}
|
||||
onChange={() => {}}
|
||||
></OlCheckbox>
|
||||
<OlCheckbox checked={props.options.showMinimap} onChange={() => {}}></OlCheckbox>
|
||||
<span>Show minimap</span>
|
||||
<kbd
|
||||
className={`
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
import React, { useState } from "react";
|
||||
import { OlStateButton } from "../components/olstatebutton";
|
||||
import {
|
||||
faGamepad,
|
||||
faRuler,
|
||||
faPencil,
|
||||
faEllipsisV,
|
||||
faCog,
|
||||
faQuestionCircle,
|
||||
faPlusSquare
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { faGamepad, faRuler, faPencil, faEllipsisV, faCog, faQuestionCircle, faPlusSquare } from "@fortawesome/free-solid-svg-icons";
|
||||
import { EventsConsumer } from "../../eventscontext";
|
||||
import { StateConsumer } from "../../statecontext";
|
||||
|
||||
@@ -20,7 +12,7 @@ export function SideBar() {
|
||||
{(events) => (
|
||||
<nav
|
||||
className={`
|
||||
flex flex-col z-ui-4 h-full bg-gray-300
|
||||
absolute left-0 z-20 flex h-full flex-col bg-gray-300
|
||||
dark:bg-olympus-900
|
||||
`}
|
||||
>
|
||||
@@ -52,12 +44,7 @@ export function SideBar() {
|
||||
icon={faGamepad}
|
||||
tooltip=""
|
||||
></OlStateButton>
|
||||
<OlStateButton
|
||||
onClick={events.toggleMeasureMenuVisible}
|
||||
checked={appState.measureMenuVisible}
|
||||
icon={faRuler}
|
||||
tooltip=""
|
||||
></OlStateButton>
|
||||
<OlStateButton onClick={events.toggleMeasureMenuVisible} checked={appState.measureMenuVisible} icon={faRuler} tooltip=""></OlStateButton>
|
||||
<OlStateButton
|
||||
onClick={events.toggleDrawingMenuVisible}
|
||||
checked={appState.drawingMenuVisible}
|
||||
@@ -73,9 +60,7 @@ export function SideBar() {
|
||||
`}
|
||||
>
|
||||
<OlStateButton
|
||||
onClick={() =>
|
||||
window.open("https://github.com/Pax1601/DCSOlympus/wiki")
|
||||
}
|
||||
onClick={() => window.open("https://github.com/Pax1601/DCSOlympus/wiki")}
|
||||
checked={false}
|
||||
icon={faQuestionCircle}
|
||||
tooltip="Open user guide on separate window"
|
||||
|
||||
@@ -20,26 +20,15 @@ import { getUnitsByLabel } from "../../other/utils";
|
||||
|
||||
library.add(faPlus);
|
||||
|
||||
export function SpawnMenu(props: {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
children?: JSX.Element | JSX.Element[];
|
||||
}) {
|
||||
var [blueprint, setBlueprint] = useState(null as null | UnitBlueprint);
|
||||
var [filterString, setFilterString] = useState("");
|
||||
export function SpawnMenu(props: { open: boolean; onClose: () => void; children?: JSX.Element | JSX.Element[] }) {
|
||||
const [blueprint, setBlueprint] = useState(null as null | UnitBlueprint);
|
||||
const [filterString, setFilterString] = useState("");
|
||||
|
||||
const [
|
||||
filteredAircraft,
|
||||
filteredHelicopters,
|
||||
filteredAirDefense,
|
||||
filteredGroundUnits,
|
||||
filteredNavyUnits,
|
||||
] = getUnitsByLabel(filterString);
|
||||
const [filteredAircraft, filteredHelicopters, filteredAirDefense, filteredGroundUnits, filteredNavyUnits] = getUnitsByLabel(filterString);
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.open) {
|
||||
if (getApp()?.getMap()?.getState() === SPAWN_UNIT)
|
||||
getApp().getMap().setState(IDLE);
|
||||
if (getApp()?.getMap()?.getState() === SPAWN_UNIT) getApp().getMap().setState(IDLE);
|
||||
if (blueprint !== null) setBlueprint(null);
|
||||
}
|
||||
});
|
||||
@@ -58,10 +47,7 @@ export function SpawnMenu(props: {
|
||||
<>
|
||||
{blueprint === null && (
|
||||
<div className="p-5">
|
||||
<OlSearchBar
|
||||
onChange={(value) => setFilterString(value)}
|
||||
text={filterString}
|
||||
/>
|
||||
<OlSearchBar onChange={(value) => setFilterString(value)} text={filterString} />
|
||||
<OlAccordion title={`Aircraft`}>
|
||||
<div
|
||||
className={`
|
||||
@@ -69,14 +55,7 @@ export function SpawnMenu(props: {
|
||||
`}
|
||||
>
|
||||
{Object.entries(filteredAircraft).map((entry) => {
|
||||
return (
|
||||
<OlUnitEntryList
|
||||
key={entry[0]}
|
||||
icon={olButtonsVisibilityAircraft}
|
||||
blueprint={entry[1]}
|
||||
onClick={() => setBlueprint(entry[1])}
|
||||
/>
|
||||
);
|
||||
return <OlUnitEntryList key={entry[0]} icon={olButtonsVisibilityAircraft} blueprint={entry[1]} onClick={() => setBlueprint(entry[1])} />;
|
||||
})}
|
||||
</div>
|
||||
</OlAccordion>
|
||||
@@ -87,14 +66,7 @@ export function SpawnMenu(props: {
|
||||
`}
|
||||
>
|
||||
{Object.entries(filteredHelicopters).map((entry) => {
|
||||
return (
|
||||
<OlUnitEntryList
|
||||
key={entry[0]}
|
||||
icon={olButtonsVisibilityHelicopter}
|
||||
blueprint={entry[1]}
|
||||
onClick={() => setBlueprint(entry[1])}
|
||||
/>
|
||||
);
|
||||
return <OlUnitEntryList key={entry[0]} icon={olButtonsVisibilityHelicopter} blueprint={entry[1]} onClick={() => setBlueprint(entry[1])} />;
|
||||
})}
|
||||
</div>
|
||||
</OlAccordion>
|
||||
@@ -105,14 +77,7 @@ export function SpawnMenu(props: {
|
||||
`}
|
||||
>
|
||||
{Object.entries(filteredAirDefense).map((entry) => {
|
||||
return (
|
||||
<OlUnitEntryList
|
||||
key={entry[0]}
|
||||
icon={olButtonsVisibilityGroundunitSam}
|
||||
blueprint={entry[1]}
|
||||
onClick={() => setBlueprint(entry[1])}
|
||||
/>
|
||||
);
|
||||
return <OlUnitEntryList key={entry[0]} icon={olButtonsVisibilityGroundunitSam} blueprint={entry[1]} onClick={() => setBlueprint(entry[1])} />;
|
||||
})}
|
||||
</div>
|
||||
</OlAccordion>
|
||||
@@ -123,14 +88,7 @@ export function SpawnMenu(props: {
|
||||
`}
|
||||
>
|
||||
{Object.entries(filteredGroundUnits).map((entry) => {
|
||||
return (
|
||||
<OlUnitEntryList
|
||||
key={entry[0]}
|
||||
icon={olButtonsVisibilityGroundunit}
|
||||
blueprint={entry[1]}
|
||||
onClick={() => setBlueprint(entry[1])}
|
||||
/>
|
||||
);
|
||||
return <OlUnitEntryList key={entry[0]} icon={olButtonsVisibilityGroundunit} blueprint={entry[1]} onClick={() => setBlueprint(entry[1])} />;
|
||||
})}
|
||||
</div>
|
||||
</OlAccordion>
|
||||
@@ -141,14 +99,7 @@ export function SpawnMenu(props: {
|
||||
`}
|
||||
>
|
||||
{Object.entries(filteredNavyUnits).map((entry) => {
|
||||
return (
|
||||
<OlUnitEntryList
|
||||
key={entry[0]}
|
||||
icon={olButtonsVisibilityNavyunit}
|
||||
blueprint={entry[1]}
|
||||
onClick={() => setBlueprint(entry[1])}
|
||||
/>
|
||||
);
|
||||
return <OlUnitEntryList key={entry[0]} icon={olButtonsVisibilityNavyunit} blueprint={entry[1]} onClick={() => setBlueprint(entry[1])} />;
|
||||
})}
|
||||
</div>
|
||||
</OlAccordion>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,14 +9,10 @@ import { FaInfoCircle } from "react-icons/fa";
|
||||
import { FaChevronLeft, FaChevronRight } from "react-icons/fa6";
|
||||
|
||||
export function UnitMouseControlBar(props: {}) {
|
||||
var [open, setOpen] = useState(false);
|
||||
var [selectedUnits, setSelectedUnits] = useState([] as Unit[]);
|
||||
var [contextActionsSet, setContextActionsSet] = useState(
|
||||
new ContextActionSet()
|
||||
);
|
||||
var [activeContextAction, setActiveContextAction] = useState(
|
||||
null as null | ContextAction
|
||||
);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [selectedUnits, setSelectedUnits] = useState([] as Unit[]);
|
||||
const [contextActionsSet, setContextActionsSet] = useState(new ContextActionSet());
|
||||
const [activeContextAction, setActiveContextAction] = useState(null as null | ContextAction);
|
||||
const [scrolledLeft, setScrolledLeft] = useState(true);
|
||||
const [scrolledRight, setScrolledRight] = useState(false);
|
||||
|
||||
@@ -87,7 +83,7 @@ export function UnitMouseControlBar(props: {}) {
|
||||
<div
|
||||
className={`
|
||||
absolute left-[50%] top-16 flex max-w-[80%]
|
||||
translate-x-[calc(-50%+2rem)] gap-2 rounded-md bg-gray-200 z-ui-2
|
||||
translate-x-[calc(-50%+2rem)] gap-2 rounded-md bg-gray-200
|
||||
dark:bg-olympus-900
|
||||
`}
|
||||
>
|
||||
@@ -100,40 +96,34 @@ export function UnitMouseControlBar(props: {}) {
|
||||
`}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
className="flex gap-2 overflow-x-auto no-scrollbar p-2"
|
||||
onScroll={(ev) => onScroll(ev.target)}
|
||||
ref={scrollRef}
|
||||
>
|
||||
{Object.values(contextActionsSet.getContextActions()).map(
|
||||
(contextAction) => {
|
||||
return (
|
||||
<OlStateButton
|
||||
checked={contextAction === activeContextAction}
|
||||
icon={contextAction.getIcon()}
|
||||
tooltip={contextAction.getLabel()}
|
||||
onClick={() => {
|
||||
if (contextAction.getOptions().executeImmediately) {
|
||||
setActiveContextAction(null);
|
||||
contextAction.executeCallback(null, null);
|
||||
<div className="flex gap-2 overflow-x-auto no-scrollbar p-2" onScroll={(ev) => onScroll(ev.target)} ref={scrollRef}>
|
||||
{Object.values(contextActionsSet.getContextActions()).map((contextAction) => {
|
||||
return (
|
||||
<OlStateButton
|
||||
checked={contextAction === activeContextAction}
|
||||
icon={contextAction.getIcon()}
|
||||
tooltip={contextAction.getLabel()}
|
||||
onClick={() => {
|
||||
if (contextAction.getOptions().executeImmediately) {
|
||||
setActiveContextAction(null);
|
||||
contextAction.executeCallback(null, null);
|
||||
} else {
|
||||
if (activeContextAction != contextAction) {
|
||||
setActiveContextAction(contextAction);
|
||||
getApp().getMap().setState(CONTEXT_ACTION, {
|
||||
contextAction: contextAction,
|
||||
});
|
||||
} else {
|
||||
if (activeContextAction != contextAction) {
|
||||
setActiveContextAction(contextAction);
|
||||
getApp().getMap().setState(CONTEXT_ACTION, {
|
||||
contextAction: contextAction,
|
||||
});
|
||||
} else {
|
||||
setActiveContextAction(null);
|
||||
getApp().getMap().setState(CONTEXT_ACTION, {
|
||||
contextAction: null,
|
||||
});
|
||||
}
|
||||
setActiveContextAction(null);
|
||||
getApp().getMap().setState(CONTEXT_ACTION, {
|
||||
contextAction: null,
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
)}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{!scrolledRight && (
|
||||
<FaChevronRight
|
||||
@@ -148,9 +138,9 @@ export function UnitMouseControlBar(props: {}) {
|
||||
{activeContextAction && (
|
||||
<div
|
||||
className={`
|
||||
absolute left-[50%] top-32 flex translate-x-[calc(-50%+2rem)]
|
||||
items-center gap-2 rounded-md bg-gray-200 p-4 z-ui-1
|
||||
min-w-[300px]
|
||||
absolute left-[50%] top-32 flex min-w-[300px]
|
||||
translate-x-[calc(-50%+2rem)] items-center gap-2 rounded-md
|
||||
bg-gray-200 p-4
|
||||
dark:bg-olympus-800
|
||||
`}
|
||||
>
|
||||
|
||||
@@ -21,14 +21,12 @@ export function UnitSpawnMenu(props: { blueprint: UnitBlueprint }) {
|
||||
const altitudeStep = 500;
|
||||
|
||||
/* State initialization */
|
||||
var [spawnCoalition, setSpawnCoalition] = useState("blue" as Coalition);
|
||||
var [spawnNumber, setSpawnNumber] = useState(1);
|
||||
var [spawnRole, setSpawnRole] = useState("");
|
||||
var [spawnLoadoutName, setSpawnLoadout] = useState("");
|
||||
var [spawnAltitude, setSpawnAltitude] = useState(
|
||||
(maxAltitude - minAltitude) / 2
|
||||
);
|
||||
var [spawnAltitudeType, setSpawnAltitudeType] = useState(false);
|
||||
const [spawnCoalition, setSpawnCoalition] = useState("blue" as Coalition);
|
||||
const [spawnNumber, setSpawnNumber] = useState(1);
|
||||
const [spawnRole, setSpawnRole] = useState("");
|
||||
const [spawnLoadoutName, setSpawnLoadout] = useState("");
|
||||
const [spawnAltitude, setSpawnAltitude] = useState((maxAltitude - minAltitude) / 2);
|
||||
const [spawnAltitudeType, setSpawnAltitudeType] = useState(false);
|
||||
|
||||
/* When the menu is opened show the unit preview on the map as a cursor */
|
||||
useEffect(() => {
|
||||
@@ -53,8 +51,7 @@ export function UnitSpawnMenu(props: { blueprint: UnitBlueprint }) {
|
||||
},
|
||||
});
|
||||
} else {
|
||||
if (getApp()?.getMap()?.getState() === SPAWN_UNIT)
|
||||
getApp().getMap().setState(IDLE);
|
||||
if (getApp()?.getMap()?.getState() === SPAWN_UNIT) getApp().getMap().setState(IDLE);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -76,9 +73,7 @@ export function UnitSpawnMenu(props: { blueprint: UnitBlueprint }) {
|
||||
});
|
||||
|
||||
/* Initialize the loadout */
|
||||
spawnLoadoutName === "" &&
|
||||
loadouts.length > 0 &&
|
||||
setSpawnLoadout(loadouts[0].name);
|
||||
spawnLoadoutName === "" && loadouts.length > 0 && setSpawnLoadout(loadouts[0].name);
|
||||
const spawnLoadout = props.blueprint.loadouts?.find((loadout) => {
|
||||
return loadout.name === spawnLoadoutName;
|
||||
});
|
||||
@@ -111,13 +106,7 @@ export function UnitSpawnMenu(props: { blueprint: UnitBlueprint }) {
|
||||
setSpawnNumber(Math.min(maxNumber, spawnNumber + 1));
|
||||
}}
|
||||
onChange={(ev) => {
|
||||
!isNaN(Number(ev.target.value)) &&
|
||||
setSpawnNumber(
|
||||
Math.max(
|
||||
minNumber,
|
||||
Math.min(maxNumber, Number(ev.target.value))
|
||||
)
|
||||
);
|
||||
!isNaN(Number(ev.target.value)) && setSpawnNumber(Math.max(minNumber, Math.min(maxNumber, Number(ev.target.value))));
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -143,12 +132,7 @@ export function UnitSpawnMenu(props: { blueprint: UnitBlueprint }) {
|
||||
`}
|
||||
>{`${Intl.NumberFormat("en-US").format(spawnAltitude)} FT`}</span>
|
||||
</div>
|
||||
<OlLabelToggle
|
||||
toggled={spawnAltitudeType}
|
||||
leftLabel={"AGL"}
|
||||
rightLabel={"ASL"}
|
||||
onClick={() => setSpawnAltitudeType(!spawnAltitudeType)}
|
||||
/>
|
||||
<OlLabelToggle toggled={spawnAltitudeType} leftLabel={"AGL"} rightLabel={"ASL"} onClick={() => setSpawnAltitudeType(!spawnAltitudeType)} />
|
||||
</div>
|
||||
<OlRangeSlider
|
||||
onChange={(ev) => setSpawnAltitude(Number(ev.target.value))}
|
||||
|
||||
@@ -11,14 +11,7 @@ import { MainMenu } from "./panels/mainmenu";
|
||||
import { SideBar } from "./panels/sidebar";
|
||||
import { Options } from "./panels/options";
|
||||
import { MapHiddenTypes, MapOptions } from "../types/types";
|
||||
import {
|
||||
BLUE_COMMANDER,
|
||||
GAME_MASTER,
|
||||
IDLE,
|
||||
MAP_HIDDEN_TYPES_DEFAULTS,
|
||||
MAP_OPTIONS_DEFAULTS,
|
||||
RED_COMMANDER,
|
||||
} from "../constants/constants";
|
||||
import { BLUE_COMMANDER, GAME_MASTER, IDLE, MAP_HIDDEN_TYPES_DEFAULTS, MAP_OPTIONS_DEFAULTS, RED_COMMANDER } from "../constants/constants";
|
||||
import { getApp, setupApp } from "../olympusapp";
|
||||
import { LoginModal } from "./modals/login";
|
||||
import { sha256 } from "js-sha256";
|
||||
@@ -39,22 +32,22 @@ export type OlympusState = {
|
||||
};
|
||||
|
||||
export function UI() {
|
||||
var [loginModalVisible, setLoginModalVisible] = useState(true);
|
||||
var [mainMenuVisible, setMainMenuVisible] = useState(false);
|
||||
var [spawnMenuVisible, setSpawnMenuVisible] = useState(false);
|
||||
var [unitControlMenuVisible, setUnitControlMenuVisible] = useState(false);
|
||||
var [measureMenuVisible, setMeasureMenuVisible] = useState(false);
|
||||
var [drawingMenuVisible, setDrawingMenuVisible] = useState(false);
|
||||
var [optionsMenuVisible, setOptionsMenuVisible] = useState(false);
|
||||
var [mapHiddenTypes, setMapHiddenTypes] = useState(MAP_HIDDEN_TYPES_DEFAULTS);
|
||||
var [mapOptions, setMapOptions] = useState(MAP_OPTIONS_DEFAULTS);
|
||||
var [checkingPassword, setCheckingPassword] = useState(false);
|
||||
var [loginError, setLoginError] = useState(false);
|
||||
var [commandMode, setCommandMode] = useState(null as null | string);
|
||||
var [mapSources, setMapSources] = useState([] as string[]);
|
||||
var [activeMapSource, setActiveMapSource] = useState("");
|
||||
var [mapBoxSelection, setMapBoxSelection] = useState(false);
|
||||
var [mapState, setMapState] = useState(IDLE);
|
||||
const [loginModalVisible, setLoginModalVisible] = useState(true);
|
||||
const [mainMenuVisible, setMainMenuVisible] = useState(false);
|
||||
const [spawnMenuVisible, setSpawnMenuVisible] = useState(false);
|
||||
const [unitControlMenuVisible, setUnitControlMenuVisible] = useState(false);
|
||||
const [measureMenuVisible, setMeasureMenuVisible] = useState(false);
|
||||
const [drawingMenuVisible, setDrawingMenuVisible] = useState(false);
|
||||
const [optionsMenuVisible, setOptionsMenuVisible] = useState(false);
|
||||
const [mapHiddenTypes, setMapHiddenTypes] = useState(MAP_HIDDEN_TYPES_DEFAULTS);
|
||||
const [mapOptions, setMapOptions] = useState(MAP_OPTIONS_DEFAULTS);
|
||||
const [checkingPassword, setCheckingPassword] = useState(false);
|
||||
const [loginError, setLoginError] = useState(false);
|
||||
const [commandMode, setCommandMode] = useState(null as null | string);
|
||||
const [mapSources, setMapSources] = useState([] as string[]);
|
||||
const [activeMapSource, setActiveMapSource] = useState("");
|
||||
const [mapBoxSelection, setMapBoxSelection] = useState(false);
|
||||
const [mapState, setMapState] = useState(IDLE);
|
||||
|
||||
document.addEventListener("hiddenTypesChanged", (ev) => {
|
||||
setMapHiddenTypes({ ...getApp().getMap().getHiddenTypes() });
|
||||
@@ -65,10 +58,9 @@ export function UI() {
|
||||
});
|
||||
|
||||
document.addEventListener("mapStateChanged", (ev) => {
|
||||
if ((ev as CustomEvent).detail === IDLE && mapState !== IDLE)
|
||||
hideAllMenus();
|
||||
|
||||
setMapState(String((ev as CustomEvent).detail))
|
||||
if ((ev as CustomEvent).detail === IDLE && mapState !== IDLE) hideAllMenus();
|
||||
|
||||
setMapState(String((ev as CustomEvent).detail));
|
||||
});
|
||||
|
||||
document.addEventListener("mapSourceChanged", (ev) => {
|
||||
@@ -78,9 +70,7 @@ export function UI() {
|
||||
|
||||
document.addEventListener("configLoaded", (ev) => {
|
||||
let config = getApp().getConfig();
|
||||
var sources = Object.keys(config.mapMirrors).concat(
|
||||
Object.keys(config.mapLayers)
|
||||
);
|
||||
var sources = Object.keys(config.mapMirrors).concat(Object.keys(config.mapLayers));
|
||||
setMapSources(sources);
|
||||
setActiveMapSource(sources[0]);
|
||||
});
|
||||
@@ -112,9 +102,7 @@ export function UI() {
|
||||
(response) => {
|
||||
const commandMode = response.mission.commandModeOptions.commandMode;
|
||||
try {
|
||||
[GAME_MASTER, BLUE_COMMANDER, RED_COMMANDER].includes(commandMode)
|
||||
? setCommandMode(commandMode)
|
||||
: setLoginError(true);
|
||||
[GAME_MASTER, BLUE_COMMANDER, RED_COMMANDER].includes(commandMode) ? setCommandMode(commandMode) : setLoginError(true);
|
||||
} catch {
|
||||
setLoginError(true);
|
||||
}
|
||||
@@ -197,14 +185,18 @@ export function UI() {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<div className="absolute left-0 top-0 flex h-full w-full flex-col">
|
||||
<div
|
||||
className={`
|
||||
absolute left-0 top-0 flex h-full w-full flex-col
|
||||
`}
|
||||
>
|
||||
<Header />
|
||||
<div className="flex h-full">
|
||||
<div className="flex justify-reverse h-full">
|
||||
{loginModalVisible && (
|
||||
<>
|
||||
<div
|
||||
className={`
|
||||
fixed left-0 top-0 h-full w-full z-ui-5 bg-[#111111]/95
|
||||
fixed left-0 top-0 z-30 h-full w-full bg-[#111111]/95
|
||||
`}
|
||||
></div>
|
||||
<LoginModal
|
||||
@@ -223,32 +215,17 @@ export function UI() {
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<SideBar />
|
||||
<MainMenu
|
||||
open={mainMenuVisible}
|
||||
onClose={() => setMainMenuVisible(false)}
|
||||
/>
|
||||
<SpawnMenu
|
||||
open={spawnMenuVisible}
|
||||
onClose={() => setSpawnMenuVisible(false)}
|
||||
/>
|
||||
<Options
|
||||
open={optionsMenuVisible}
|
||||
onClose={() => setOptionsMenuVisible(false)}
|
||||
options={mapOptions}
|
||||
/>
|
||||
<div id="map-container" className="z-0 h-full w-screen" />
|
||||
<MainMenu open={mainMenuVisible} onClose={() => setMainMenuVisible(false)} />
|
||||
<SpawnMenu open={spawnMenuVisible} onClose={() => setSpawnMenuVisible(false)} />
|
||||
<Options open={optionsMenuVisible} onClose={() => setOptionsMenuVisible(false)} options={mapOptions} />
|
||||
<MiniMapPanel />
|
||||
<ControlsPanel />
|
||||
<UnitControlMenu
|
||||
open={unitControlMenuVisible}
|
||||
onClose={() => setUnitControlMenuVisible(false)}
|
||||
/>
|
||||
<DrawingMenu
|
||||
open={drawingMenuVisible}
|
||||
onClose={() => setDrawingMenuVisible(false)}
|
||||
/>
|
||||
<div id="map-container" className="h-full w-screen" />
|
||||
<UnitControlMenu open={unitControlMenuVisible} onClose={() => setUnitControlMenuVisible(false)} />
|
||||
<DrawingMenu open={drawingMenuVisible} onClose={() => setDrawingMenuVisible(false)} />
|
||||
|
||||
<UnitMouseControlBar />
|
||||
<SideBar />
|
||||
</div>
|
||||
</div>
|
||||
</EventsProvider>
|
||||
|
||||
Reference in New Issue
Block a user