Completed advanced settings panel for tanker and AWACS

Reformatted files with larger width, reordered unused icons
This commit is contained in:
Pax1601
2024-08-07 15:32:39 +02:00
parent bc5049992a
commit 224dc5a688
158 changed files with 5813 additions and 6404 deletions

View File

@@ -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>

View File

@@ -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}

View File

@@ -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>

View File

@@ -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}

View File

@@ -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>
);

View File

@@ -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

View File

@@ -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
`}

View File

@@ -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>

View File

@@ -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);

View File

@@ -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} />}
</>

View 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>
);
}

View File

@@ -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}

View File

@@ -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
`}
>

View File

@@ -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

View File

@@ -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}

View File

@@ -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={`

View File

@@ -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
`}
>

View File

@@ -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>

View File

@@ -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>
)}

View File

@@ -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>

View File

@@ -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

View File

@@ -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
`}
/>

View File

@@ -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

View File

@@ -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

View File

@@ -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={`

View File

@@ -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"

View File

@@ -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

View File

@@ -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
`}
>

View File

@@ -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))}

View File

@@ -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>