diff --git a/.gitignore b/.gitignore index 7a2f4b1f..2f1bffe6 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ node_modules /client/plugins/controltips/index.js hgt /client/public/databases/units/old +/client/plugins/databasemanager/index.js diff --git a/client/plugins/databasemanager/index.js b/client/plugins/databasemanager/index.js index db4029ad..d434ec3d 100644 --- a/client/plugins/databasemanager/index.js +++ b/client/plugins/databasemanager/index.js @@ -508,7 +508,7 @@ class GroundUnitEditor extends uniteditor_1.UnitEditor { * @param blueprint The blueprint to edit */ setBlueprint(blueprint) { - var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s; + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u; __classPrivateFieldSet(this, _GroundUnitEditor_blueprint, blueprint, "f"); if (__classPrivateFieldGet(this, _GroundUnitEditor_blueprint, "f") !== null) { this.contentDiv2.replaceChildren(); @@ -526,18 +526,20 @@ class GroundUnitEditor extends uniteditor_1.UnitEditor { (0, utils_1.addStringInput)(this.contentDiv2, "Acquisition range [m]", (_c = String(blueprint.acquisitionRange)) !== null && _c !== void 0 ? _c : "", "number", (value) => { blueprint.acquisitionRange = parseFloat(value); }); (0, utils_1.addStringInput)(this.contentDiv2, "Engagement range [m]", (_d = String(blueprint.engagementRange)) !== null && _d !== void 0 ? _d : "", "number", (value) => { blueprint.engagementRange = parseFloat(value); }); (0, utils_1.addStringInput)(this.contentDiv2, "Targeting range [m]", (_e = String(blueprint.targetingRange)) !== null && _e !== void 0 ? _e : "", "number", (value) => { blueprint.targetingRange = parseFloat(value); }); - (0, utils_1.addStringInput)(this.contentDiv2, "Barrel height [m]", (_f = String(blueprint.barrelHeight)) !== null && _f !== void 0 ? _f : "", "number", (value) => { blueprint.barrelHeight = parseFloat(value); }); - (0, utils_1.addStringInput)(this.contentDiv2, "Muzzle velocity [m/s]", (_g = String(blueprint.muzzleVelocity)) !== null && _g !== void 0 ? _g : "", "number", (value) => { blueprint.muzzleVelocity = parseFloat(value); }); - (0, utils_1.addStringInput)(this.contentDiv2, "Aim time [s]", (_h = String(blueprint.aimTime)) !== null && _h !== void 0 ? _h : "", "number", (value) => { blueprint.aimTime = parseFloat(value); }); - (0, utils_1.addStringInput)(this.contentDiv2, "Burst quantity", (_j = String(blueprint.shotsToFire)) !== null && _j !== void 0 ? _j : "", "number", (value) => { blueprint.shotsToFire = Math.round(parseFloat(value)); }); - (0, utils_1.addStringInput)(this.contentDiv2, "Burst base interval [s]", (_k = String(blueprint.shotsBaseInterval)) !== null && _k !== void 0 ? _k : "", "number", (value) => { blueprint.shotsBaseInterval = Math.round(parseFloat(value)); }); - (0, utils_1.addStringInput)(this.contentDiv2, "Base scatter [°]", (_l = String(blueprint.shotsBaseScatter)) !== null && _l !== void 0 ? _l : "", "number", (value) => { blueprint.shotsBaseScatter = Math.round(parseFloat(value)); }); - (0, utils_1.addCheckboxInput)(this.contentDiv2, "Can target point", (_m = blueprint.canTargetPoint) !== null && _m !== void 0 ? _m : false, (value) => { blueprint.canTargetPoint = value; }); - (0, utils_1.addCheckboxInput)(this.contentDiv2, "Can rearm", (_o = blueprint.canRearm) !== null && _o !== void 0 ? _o : false, (value) => { blueprint.canRearm = value; }); - (0, utils_1.addCheckboxInput)(this.contentDiv2, "Can operate as AAA", (_p = blueprint.canAAA) !== null && _p !== void 0 ? _p : false, (value) => { blueprint.canAAA = value; }); - (0, utils_1.addCheckboxInput)(this.contentDiv2, "Indirect fire (e.g. mortar)", (_q = blueprint.indirectFire) !== null && _q !== void 0 ? _q : false, (value) => { blueprint.indirectFire = value; }); - (0, utils_1.addStringInput)(this.contentDiv2, "Description", (_r = blueprint.description) !== null && _r !== void 0 ? _r : "", "text", (value) => { blueprint.description = value; }); - (0, utils_1.addStringInput)(this.contentDiv2, "Abilities", (_s = blueprint.abilities) !== null && _s !== void 0 ? _s : "", "text", (value) => { blueprint.abilities = value; }); + (0, utils_1.addStringInput)(this.contentDiv2, "Aim method range [m]", (_f = String(blueprint.aimMethodRange)) !== null && _f !== void 0 ? _f : "", "number", (value) => { blueprint.aimMethodRange = parseFloat(value); }); + (0, utils_1.addStringInput)(this.contentDiv2, "Barrel height [m]", (_g = String(blueprint.barrelHeight)) !== null && _g !== void 0 ? _g : "", "number", (value) => { blueprint.barrelHeight = parseFloat(value); }); + (0, utils_1.addStringInput)(this.contentDiv2, "Muzzle velocity [m/s]", (_h = String(blueprint.muzzleVelocity)) !== null && _h !== void 0 ? _h : "", "number", (value) => { blueprint.muzzleVelocity = parseFloat(value); }); + (0, utils_1.addStringInput)(this.contentDiv2, "Aim time [s]", (_j = String(blueprint.aimTime)) !== null && _j !== void 0 ? _j : "", "number", (value) => { blueprint.aimTime = parseFloat(value); }); + (0, utils_1.addStringInput)(this.contentDiv2, "Shots to fire", (_k = String(blueprint.shotsToFire)) !== null && _k !== void 0 ? _k : "", "number", (value) => { blueprint.shotsToFire = Math.round(parseFloat(value)); }); + (0, utils_1.addStringInput)(this.contentDiv2, "Shots base interval [s]", (_l = String(blueprint.shotsBaseInterval)) !== null && _l !== void 0 ? _l : "", "number", (value) => { blueprint.shotsBaseInterval = Math.round(parseFloat(value)); }); + (0, utils_1.addStringInput)(this.contentDiv2, "Shots base scatter [°]", (_m = String(blueprint.shotsBaseScatter)) !== null && _m !== void 0 ? _m : "", "number", (value) => { blueprint.shotsBaseScatter = Math.round(parseFloat(value)); }); + (0, utils_1.addStringInput)(this.contentDiv2, "Alertness time constant [s]", (_o = String(blueprint.alertnessTimeConstant)) !== null && _o !== void 0 ? _o : "", "number", (value) => { blueprint.alertnessTimeConstant = Math.round(parseFloat(value)); }); + (0, utils_1.addCheckboxInput)(this.contentDiv2, "Can target point", (_p = blueprint.canTargetPoint) !== null && _p !== void 0 ? _p : false, (value) => { blueprint.canTargetPoint = value; }); + (0, utils_1.addCheckboxInput)(this.contentDiv2, "Can rearm", (_q = blueprint.canRearm) !== null && _q !== void 0 ? _q : false, (value) => { blueprint.canRearm = value; }); + (0, utils_1.addCheckboxInput)(this.contentDiv2, "Can operate as AAA", (_r = blueprint.canAAA) !== null && _r !== void 0 ? _r : false, (value) => { blueprint.canAAA = value; }); + (0, utils_1.addCheckboxInput)(this.contentDiv2, "Indirect fire (e.g. mortar)", (_s = blueprint.indirectFire) !== null && _s !== void 0 ? _s : false, (value) => { blueprint.indirectFire = value; }); + (0, utils_1.addStringInput)(this.contentDiv2, "Description", (_t = blueprint.description) !== null && _t !== void 0 ? _t : "", "text", (value) => { blueprint.description = value; }); + (0, utils_1.addStringInput)(this.contentDiv2, "Abilities", (_u = blueprint.abilities) !== null && _u !== void 0 ? _u : "", "text", (value) => { blueprint.abilities = value; }); } } /** Add a new empty blueprint @@ -751,9 +753,9 @@ class UnitEditor { this.database = JSON.parse(JSON.stringify({ blueprints: database.getBlueprints(true) })); } /** Show the editor - * + * @param filter String filter */ - show() { + show(filter = "") { this.visible = true; this.contentDiv1.replaceChildren(); this.contentDiv2.replaceChildren(); @@ -763,17 +765,16 @@ class UnitEditor { var title = document.createElement("label"); title.innerText = "Units list"; this.contentDiv1.appendChild(title); - (0, utils_1.addBlueprintsScroll)(this.contentDiv1, this.database, (key) => { - if (this.database != null) - this.setBlueprint(this.database.blueprints[key]); - }); - (0, utils_1.addNewElementInput)(this.contentDiv1, (ev, input) => { - if (input.value != "") - this.addBlueprint((input).value); - }); + var filterInput = document.createElement("input"); + filterInput.value = filter; + this.contentDiv1.appendChild(filterInput); + filterInput.onchange = (e) => { + this.show(e.target.value); + }; + this.addBlueprints(filter); } } - /** Hid the editor + /** Hide the editor * */ hide() { @@ -789,6 +790,22 @@ class UnitEditor { getDatabase() { return this.database; } + /** + * + * @param filter String filter + */ + addBlueprints(filter = "") { + if (this.database) { + (0, utils_1.addBlueprintsScroll)(this.contentDiv1, this.database, filter, (key) => { + if (this.database != null) + this.setBlueprint(this.database.blueprints[key]); + }); + (0, utils_1.addNewElementInput)(this.contentDiv1, (ev, input) => { + if (input.value != "") + this.addBlueprint((input).value); + }); + } + } } exports.UnitEditor = UnitEditor; @@ -958,36 +975,56 @@ exports.addNewElementInput = addNewElementInput; * * @param div The HTMLElement that will contain the list * @param database The database that will be used to fill the list of blueprints + * @param filter A string filter that will be executed to filter the blueprints to add * @param callback Callback called when the user clicks on one of the elements */ -function addBlueprintsScroll(div, database, callback) { +function addBlueprintsScroll(div, database, filter, callback) { var scrollDiv = document.createElement("div"); scrollDiv.classList.add("dm-scroll-container"); if (database !== null) { var blueprints = database.blueprints; for (let key of Object.keys(blueprints).sort((a, b) => a.localeCompare(b, undefined, { sensitivity: 'base' }))) { - var rowDiv = document.createElement("div"); - scrollDiv.appendChild(rowDiv); - var text = document.createElement("label"); - text.textContent = key; - text.onclick = () => callback(key); - rowDiv.appendChild(text); - let checkbox = document.createElement("input"); - checkbox.type = "checkbox"; - checkbox.checked = blueprints[key].enabled; - checkbox.onclick = () => { - console.log(checkbox.checked); - blueprints[key].enabled = checkbox.checked; - }; - rowDiv.appendChild(checkbox); - /* This button allows to remove an element from the list. It requires a refresh. */ - var button = document.createElement("button"); - button.innerText = "X"; - button.onclick = () => { - delete blueprints[key]; - div.dispatchEvent(new Event("refresh")); - }; - rowDiv.appendChild(button); + var addKey = true; + if (filter !== "") { + try { + var blueprint = blueprints[key]; + addKey = eval(filter); + } + catch (_a) { + console.error("An error has occurred evaluating the blueprint filter"); + } + } + if (addKey) { + var rowDiv = document.createElement("div"); + scrollDiv.appendChild(rowDiv); + let text = document.createElement("label"); + text.textContent = key; + text.onclick = () => { + callback(key); + const collection = document.getElementsByClassName("blueprint-selected"); + for (let i = 0; i < collection.length; i++) { + collection[i].classList.remove("blueprint-selected"); + } + text.classList.add("blueprint-selected"); + }; + rowDiv.appendChild(text); + let checkbox = document.createElement("input"); + checkbox.type = "checkbox"; + checkbox.checked = blueprints[key].enabled; + checkbox.onclick = () => { + console.log(checkbox.checked); + blueprints[key].enabled = checkbox.checked; + }; + rowDiv.appendChild(checkbox); + /* This button allows to remove an element from the list. It requires a refresh. */ + var button = document.createElement("button"); + button.innerText = "X"; + button.onclick = () => { + delete blueprints[key]; + div.dispatchEvent(new Event("refresh")); + }; + rowDiv.appendChild(button); + } } } div.appendChild(scrollDiv); @@ -1043,7 +1080,8 @@ function arrayToString(array) { } exports.arrayToString = arrayToString; function stringToArray(input) { - return input.match(/(\w)+/g) || []; + var _a; + return (_a = input.match(/(\w)+/g)) !== null && _a !== void 0 ? _a : []; } exports.stringToArray = stringToArray; diff --git a/client/plugins/databasemanager/src/utils.ts b/client/plugins/databasemanager/src/utils.ts index 004a8b84..18639612 100644 --- a/client/plugins/databasemanager/src/utils.ts +++ b/client/plugins/databasemanager/src/utils.ts @@ -287,7 +287,11 @@ export function arrayToString(array: string[]) { return "[" + array.join( ", " ) + "]"; } - +/** Converts an a single string like [val1, val2, val3] into an array + * + * @param input The input string + * @returns The array + */ export function stringToArray(input: string) { return input.match( /(\w)+/g ) ?? []; } \ No newline at end of file diff --git a/client/public/stylesheets/layout/layout.css b/client/public/stylesheets/layout/layout.css index 8dc6e68d..ba4adc98 100644 --- a/client/public/stylesheets/layout/layout.css +++ b/client/public/stylesheets/layout/layout.css @@ -1,7 +1,3 @@ -:root { - --right-panel-width:190px; -} - /* Page style */ #map-container { height: 100%; @@ -17,54 +13,10 @@ top: 10px; z-index: 99999; column-gap: 10px; + row-gap: 10px; margin-right: 320px; height: fit-content; -} - -@media (max-width: 1820px) { - #toolbar-container { - flex-direction: column; - align-items: start; - row-gap: 10px; - } -} - -#primary-toolbar { - align-items: center; - display: flex; - height: fit-content; - min-width: 650px; -} - -@media (max-width: 1820px) { - #primary-toolbar { - row-gap: 10px; - flex-wrap: wrap; - } -} - -#command-mode-toolbar { - align-items: center; - display: flex; -} - -#app-icon>.ol-select-options { - width: fit-content; -} - -#toolbar-summary { - background-image: url("/images/icon-round.png"); - background-position: 20px 22px; - background-repeat: no-repeat; - background-size: 45px 45px; - display: flex; - flex-direction: column; - padding: 20px; - text-indent: 60px; -} - -#toolbar-summary { - white-space: nowrap; + flex-wrap: wrap; } #connection-status-panel { @@ -72,7 +24,7 @@ font-size: 12px; position: absolute; right: 10px; - width: var( --right-panel-width ); + width: 190px; z-index: 9999; } @@ -84,35 +36,21 @@ position: absolute; right: 10px; row-gap: 10px; - width: var( --right-panel-width ); + width: 190px; z-index: 9999; } #unit-control-panel { height: fit-content; + width: fit-content; left: 10px; position: absolute; - top: 80px; - width: 320px; z-index: 9999; } -@media (max-width: 1820px) { - #unit-control-panel { - top: 150px; - } -} - -@media (max-width: 1350px) { - #unit-control-panel { - top: 190px; - } -} - #unit-info-panel { bottom: 20px; font-size: 12px; - left: 10px; position: absolute; width: fit-content; z-index: 9999; @@ -120,12 +58,8 @@ display: flex; flex-direction: row; justify-content: space-evenly; -} - -@media (max-width: 1525px) { - #unit-info-panel { - flex-direction: column; - } + right: 210px; + height: 180px; } #info-popup { diff --git a/client/public/stylesheets/olympus.css b/client/public/stylesheets/olympus.css index 9edb8f83..aa3c4808 100644 --- a/client/public/stylesheets/olympus.css +++ b/client/public/stylesheets/olympus.css @@ -11,6 +11,8 @@ @import url("other/contextmenus.css"); @import url("other/popup.css"); +@import url("other/toolbar.css"); + @import url("markers/airbase.css"); @import url("markers/bullseye.css"); diff --git a/client/public/stylesheets/other/toolbar.css b/client/public/stylesheets/other/toolbar.css new file mode 100644 index 00000000..c90df5f8 --- /dev/null +++ b/client/public/stylesheets/other/toolbar.css @@ -0,0 +1,74 @@ + +#primary-toolbar { + align-items: center; + display: flex; + height: fit-content; +} + +#command-mode-toolbar { + align-items: center; + display: flex; +} + +#app-icon>.ol-select-options { + width: fit-content; +} + +#toolbar-summary { + background-image: url("/images/icon-round.png"); + background-position: 20px 22px; + background-repeat: no-repeat; + background-size: 45px 45px; + display: flex; + flex-direction: column; + padding: 20px; + text-indent: 60px; +} + +#toolbar-summary { + white-space: nowrap; +} + +#toolbar-container>*:nth-child(2)>svg { + display: none; + width: 0px; + height: 0px; +} + +#toolbar-container>*:nth-child(3)>svg { + display: none; +} + +@media (max-width: 1145px) { + #toolbar-container { + flex-direction: column; + align-items: start; + } + + #toolbar-container>*:nth-child(1):not(:hover) { + width: fit-content; + height: fit-content; + } + + #toolbar-container>*:nth-child(1):not(:hover)>*:not(:first-child) { + display: none; + } + + #toolbar-container>*:not(:first-child):not(:hover) { + height: 52px; + align-items: center; + justify-content: center; + aspect-ratio: 1/1; + } + + #toolbar-container>*:not(:first-child):not(:hover)>svg { + display: block; + width: 24px; + height: 24px; + filter: invert(); + } + + #toolbar-container>*:not(:first-child):not(:hover)>*:not(:first-child) { + display: none; + } +} diff --git a/client/public/stylesheets/panels/unitcontrol.css b/client/public/stylesheets/panels/unitcontrol.css index 99509503..69ecb6b5 100644 --- a/client/public/stylesheets/panels/unitcontrol.css +++ b/client/public/stylesheets/panels/unitcontrol.css @@ -3,9 +3,48 @@ body.feature-forceShowUnitControlPanel #unit-control-panel { } #unit-control-panel { + display: flex; + flex-direction: row; + column-gap: 10px; + row-gap: 10px; +} + +#unit-control-panel>div:nth-child(2) { display: flex; flex-direction: column; row-gap: 10px; + width: 300px; +} + +#unit-control-panel>*:nth-child(1) { + display: none; + padding: 14px; +} + +@media (max-width: 1145px) { + #unit-control-panel>*:nth-child(1) { + display: flex; + } + + #unit-control-panel>*:nth-child(1) svg { + display: flex; + width: 24px; + height: 24px; + filter: invert(100%); + } + + #unit-control-panel:hover>*:nth-child(1) { + display: none; + } + + #unit-control-panel:not(:hover) { + width: fit-content; + } + + #unit-control-panel:not(:hover)>*:nth-child(2), + #unit-control-panel:not(:hover)>*:nth-child(3) { + display: none; + } } #unit-control-panel h3 { diff --git a/client/public/stylesheets/panels/unitinfo.css b/client/public/stylesheets/panels/unitinfo.css index b970dfa4..3535b5b5 100644 --- a/client/public/stylesheets/panels/unitinfo.css +++ b/client/public/stylesheets/panels/unitinfo.css @@ -1,47 +1,47 @@ #unit-info-panel>* { position: relative; - min-height: 100px; bottom: 0px; } -@media (min-width: 1525px) { - #unit-info-panel>.panel-section { - border-right: 1px solid #555; - padding: 0 30px; - } - - #unit-info-panel>.panel-section:first-child { - padding-left: 0px; - } - - #unit-info-panel>.panel-section:last-child { - padding-right: 0px; - } - - #unit-info-panel>.panel-section:last-of-type { - border-right-width: 0; - } +#unit-info-panel>*:nth-child(1) { + display: flex; + width: 24px; + height: 24px; + margin: 6px; + filter: invert(100%); } -@media (max-width: 1525px) { - #unit-info-panel>.panel-section { - border-bottom: 1px solid #555; - padding: 30px 0px; - } - - #unit-info-panel>.panel-section:first-child { - padding-top: 0px; - } - - #unit-info-panel>.panel-section:last-child { - padding-bottom: 0px; - } - - #unit-info-panel>.panel-section:last-of-type { - border-bottom-width: 0; - } +#unit-info-panel:hover>*:nth-child(1) { + display: none; } +#unit-info-panel:not(:hover) { + width: fit-content; + height: fit-content; + padding: 10px; + margin: 0px; +} + +#unit-info-panel:not(:hover)>*:not(:first-child) { + display: none; +} + +#unit-info-panel>.panel-section { + border-right: 1px solid #555; + padding: 0 30px; +} + +#unit-info-panel>.panel-section:first-of-type { + padding-left: 0px; +} + +#unit-info-panel>.panel-section:last-of-type{ + padding-right: 0px; +} + +#unit-info-panel>.panel-section:last-of-type { + border-right-width: 0; +} #general { display: flex; @@ -49,6 +49,7 @@ justify-content: space-between; row-gap: 4px; position: relative; + width: 300px; } #unit-label { @@ -63,6 +64,10 @@ #unit-name { margin-bottom: 4px; padding: 0px 0; + width: 100%; + text-overflow: ellipsis; + text-wrap: nowrap; + overflow: hidden; } #current-task { @@ -87,6 +92,7 @@ display: flex; flex-direction: column; justify-content: space-between; + width: 300px; } #loadout-silhouette { @@ -101,9 +107,9 @@ column-gap: 8px; display: flex; flex-flow: column nowrap; - max-height: 108px; - padding-right:40px; + height: 100px; row-gap: 6px; + padding-right: 10px; } #loadout-items>* { diff --git a/client/public/stylesheets/style/style.css b/client/public/stylesheets/style/style.css index eb16edde..1ff9293e 100644 --- a/client/public/stylesheets/style/style.css +++ b/client/public/stylesheets/style/style.css @@ -714,11 +714,8 @@ nav.ol-panel> :last-child { display: flex; flex-direction: column; row-gap: 5px; - position: absolute; height: fit-content; width: fit-content; - left: calc(100% + 10px); - top: 0px; } #rapid-controls button { diff --git a/client/public/themes/olympus/images/icons/circle-info-solid.svg b/client/public/themes/olympus/images/icons/circle-info-solid.svg new file mode 100644 index 00000000..652acbee --- /dev/null +++ b/client/public/themes/olympus/images/icons/circle-info-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/public/themes/olympus/images/icons/gamepad-solid.svg b/client/public/themes/olympus/images/icons/gamepad-solid.svg new file mode 100644 index 00000000..2fc91782 --- /dev/null +++ b/client/public/themes/olympus/images/icons/gamepad-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/public/themes/olympus/images/icons/person-military-pointing-solid.svg b/client/public/themes/olympus/images/icons/person-military-pointing-solid.svg new file mode 100644 index 00000000..919b3a6f --- /dev/null +++ b/client/public/themes/olympus/images/icons/person-military-pointing-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/src/olympusapp.ts b/client/src/olympusapp.ts index 22f2ebf8..66acf5e6 100644 --- a/client/src/olympusapp.ts +++ b/client/src/olympusapp.ts @@ -192,6 +192,10 @@ export class OlympusApp { this.#unitsManager = new UnitsManager(); this.#weaponsManager = new WeaponsManager(); + // Toolbars + this.getToolbarsManager().add("primaryToolbar", new PrimaryToolbar("primary-toolbar")) + .add("commandModeToolbar", new CommandModeToolbar("command-mode-toolbar")); + // Panels this.getPanelsManager() .add("connectionStatus", new ConnectionStatusPanel("connection-status-panel")) @@ -206,11 +210,7 @@ export class OlympusApp { // Popups this.getPopupsManager() .add("infoPopup", new Popup("info-popup")); - - // Toolbars - this.getToolbarsManager().add("primaryToolbar", new PrimaryToolbar("primary-toolbar")) - .add("commandModeToolbar", new CommandModeToolbar("command-mode-toolbar")); - + this.#pluginsManager = new PluginsManager(); /* Load the config file from the app server*/ diff --git a/client/src/panels/unitcontrolpanel.ts b/client/src/panels/unitcontrolpanel.ts index 78081126..1ec769f6 100644 --- a/client/src/panels/unitcontrolpanel.ts +++ b/client/src/panels/unitcontrolpanel.ts @@ -9,6 +9,7 @@ import { Switch } from "../controls/switch"; import { ROEDescriptions, ROEs, altitudeIncrements, emissionsCountermeasures, emissionsCountermeasuresDescriptions, maxAltitudeValues, maxSpeedValues, minAltitudeValues, minSpeedValues, reactionsToThreat, reactionsToThreatDescriptions, shotsIntensityDescriptions, shotsScatterDescriptions, speedIncrements } from "../constants/constants"; import { ftToM, knotsToMs, mToFt, msToKnots } from "../other/utils"; import { GeneralSettings, Radio, TACAN } from "../interfaces"; +import { PrimaryToolbar } from "../toolbars/primarytoolbar"; export class UnitControlPanel extends Panel { #altitudeSlider: Slider; @@ -136,7 +137,13 @@ export class UnitControlPanel extends Panel { this.#updateRapidControls(); }); + window.addEventListener("resize", (e: any) => this.#calculateMaxHeight()); + + const element = document.getElementById("toolbar-container"); + if (element) + new ResizeObserver(() => this.#calculateTop()).observe(element); + this.#calculateMaxHeight() this.hide(); } @@ -470,4 +477,16 @@ export class UnitControlPanel extends Panel { button.addEventListener("click", callback); return button; } + + #calculateTop() { + const element = document.getElementById("toolbar-container"); + if (element) + this.getElement().style.top = `${element.offsetTop + element.offsetHeight + 10}px`; + } + + #calculateMaxHeight() { + const element = document.getElementById("unit-control-panel-content"); + if (element) + element.style.maxHeight = `${window.innerHeight - this.getElement().offsetTop - 10}px`; + } } \ No newline at end of file diff --git a/client/views/panels/unitcontrol.ejs b/client/views/panels/unitcontrol.ejs index 85f287ac..ec9d2b3b 100644 --- a/client/views/panels/unitcontrol.ejs +++ b/client/views/panels/unitcontrol.ejs @@ -1,113 +1,115 @@ -