Added new delete method dialog

This commit is contained in:
PeekabooSteam 2023-10-27 17:26:41 +01:00
parent d14741f3b1
commit f954338c27
8 changed files with 148 additions and 43 deletions

View File

@ -140,6 +140,16 @@
align-items: center;
}
#slow-delete-popup {
align-self: center;
display:flex;
justify-self: center;
position: absolute;
width: fit-content;
height: fit-content;
z-index: 9999999999;
}
#log-panel {
position: absolute;
right: 0px;

View File

@ -699,7 +699,7 @@ nav.ol-panel> :last-child {
overflow: hidden;
width: 70%;
max-width: 1200px;
z-index: 99999;
z-index: 999999;
}
@media (min-width: 1700px) {
@ -796,7 +796,7 @@ nav.ol-panel> :last-child {
position: fixed;
top: 0px;
width: 100%;
z-index: 9999;
z-index: 99999;
}
#authentication-form {
@ -1148,7 +1148,7 @@ dl.ol-data-grid dd {
background-color: var(--background-slate-blue);
color: white;
position: absolute;
z-index: 9999;
z-index: 999999;
}
.ol-panel.ol-dialog {
@ -1178,8 +1178,10 @@ dl.ol-data-grid dd {
}
.ol-dialog-footer {
align-content: center;
border-top: 1px solid var(--background-grey);
display: flex;
justify-content: center;
padding-top: 15px;
row-gap: 10px;
}

View File

@ -209,4 +209,7 @@ export const MGRS_PRECISION_10KM = 2;
export const MGRS_PRECISION_1KM = 3;
export const MGRS_PRECISION_100M = 4;
export const MGRS_PRECISION_10M = 5;
export const MGRS_PRECISION_1M = 6;
export const MGRS_PRECISION_1M = 6;
export const DELETE_CYCLE_TIME = 0.1;
export const DELETE_SLOW_THRESHOLD = 50;

View File

@ -0,0 +1,19 @@
import { Panel } from "../panels/panel";
export class Dialog extends Panel {
constructor( element:string ) {
super( element );
}
hide() {
super.hide();
document.getElementById( "gray-out" )?.classList.toggle("hide", true);
}
show() {
super.show();
document.getElementById( "gray-out" )?.classList.toggle("hide", false);
}
}

View File

@ -34,21 +34,26 @@ export class OlympusApp {
#map: Map | null = null;
/* Managers */
#dialogManager!: Manager;
#missionManager: MissionManager | null = null;
#panelsManager: Manager | null = null;
#pluginsManager: PluginsManager | null = null;
#popupsManager: Manager | null = null;
#serverManager: ServerManager | null = null;
#shortcutManager: ShortcutManager | null = null;
#toolbarsManager: Manager | null = null;
#unitsManager: UnitsManager | null = null;
#weaponsManager: WeaponsManager | null = null;
#missionManager: MissionManager | null = null;
#pluginsManager: PluginsManager | null = null;
#panelsManager: Manager | null = null;
#popupsManager: Manager | null = null;
#toolbarsManager: Manager | null = null;
#shortcutManager: ShortcutManager | null = null;
constructor() {
}
// TODO add checks on null
getDialogManager() {
return this.#dialogManager as Manager;
}
getMap() {
return this.#map as Map;
}
@ -163,16 +168,14 @@ export class OlympusApp {
/* Initialize base functionalitites */
this.#map = new Map('map-container');
this.#serverManager = new ServerManager();
this.#unitsManager = new UnitsManager();
this.#weaponsManager = new WeaponsManager();
this.#missionManager = new MissionManager();
this.#shortcutManager = new ShortcutManager();
this.#panelsManager = new Manager();
this.#popupsManager = new Manager();
this.#serverManager = new ServerManager();
this.#shortcutManager = new ShortcutManager();
this.#toolbarsManager = new Manager();
this.#unitsManager = new UnitsManager();
this.#weaponsManager = new WeaponsManager();
// Panels
this.getPanelsManager()
@ -186,7 +189,8 @@ export class OlympusApp {
.add("unitList", new UnitListPanel("unit-list-panel", "unit-list-panel-content"))
// Popups
this.getPopupsManager().add("infoPopup", new Popup("info-popup"));
this.getPopupsManager()
.add("infoPopup", new Popup("info-popup"));
// Toolbars
this.getToolbarsManager().add("primaryToolbar", new PrimaryToolbar("primary-toolbar"))

View File

@ -541,14 +541,15 @@ export class ServerManager {
}
setConnected(newConnected: boolean) {
if (this.#connected != newConnected)
if (this.#connected != newConnected) {
newConnected ? (getApp().getPopupsManager().get("infoPopup") as Popup).setText("Connected to DCS Olympus server") : (getApp().getPopupsManager().get("infoPopup") as Popup).setText("Disconnected from DCS Olympus server");
this.#connected = newConnected;
if (this.#connected) {
document.querySelector("#splash-screen")?.classList.add("hide");
document.querySelector("#gray-out")?.classList.add("hide");
if (newConnected) {
document.getElementById("splash-screen")?.classList.add("hide");
document.getElementById("gray-out")?.classList.add("hide");
}
}
this.#connected = newConnected;
}
getConnected() {

View File

@ -4,7 +4,7 @@ import { Unit } from "./unit";
import { bearingAndDistanceToLatLng, deg2rad, getGroundElevation, getUnitDatabaseByCategory, keyEventWasInInput, latLngToMercator, mToFt, mercatorToLatLng, msToKnots, polyContains, polygonArea, randomPointInPoly, randomUnitBlueprint } from "../other/utils";
import { CoalitionArea } from "../map/coalitionarea/coalitionarea";
import { groundUnitDatabase } from "./databases/groundunitdatabase";
import { DataIndexes, GAME_MASTER, IADSDensities, IDLE, MOVE_UNIT } from "../constants/constants";
import { DELETE_CYCLE_TIME, DELETE_SLOW_THRESHOLD, DataIndexes, GAME_MASTER, IADSDensities, IDLE, MOVE_UNIT } from "../constants/constants";
import { DataExtractor } from "../server/dataextractor";
import { citiesDatabase } from "./citiesDatabase";
import { aircraftDatabase } from "./databases/aircraftdatabase";
@ -14,35 +14,40 @@ import { TemporaryUnitMarker } from "../map/markers/temporaryunitmarker";
import { Popup } from "../popups/popup";
import { HotgroupPanel } from "../panels/hotgrouppanel";
import { Contact, UnitData, UnitSpawnTable } from "../interfaces";
import { Dialog } from "../dialog/dialog";
/** The UnitsManager handles the creation, update, and control of units. Data is strictly updated by the server ONLY. This means that any interaction from the user will always and only
* result in a command to the server, executed by means of a REST PUT request. Any subsequent change in data will be reflected only when the new data is sent back by the server. This strategy allows
* to avoid client/server and client/client inconsistencies.
*/
export class UnitsManager {
#units: { [ID: number]: Unit };
#copiedUnits: UnitData[];
#selectionEventDisabled: boolean = false;
#deselectionEventDisabled: boolean = false;
#requestDetectionUpdate: boolean = false;
#selectionEventDisabled: boolean = false;
#slowDeleteDialog!:Dialog;
#units: { [ID: number]: Unit };
constructor() {
this.#units = {};
this.#copiedUnits = [];
this.#units = {};
document.addEventListener('commandModeOptionsChanged', () => { Object.values(this.#units).forEach((unit: Unit) => unit.updateVisibility()) });
document.addEventListener('contactsUpdated', (e: CustomEvent) => { this.#requestDetectionUpdate = true });
document.addEventListener('copy', () => this.selectedUnitsCopy());
document.addEventListener('paste', () => this.pasteUnits());
document.addEventListener('unitSelection', (e: CustomEvent) => this.#onUnitSelection(e.detail));
document.addEventListener('unitDeselection', (e: CustomEvent) => this.#onUnitDeselection(e.detail));
document.addEventListener('deleteSelectedUnits', () => this.selectedUnitsDelete());
document.addEventListener('explodeSelectedUnits', () => this.selectedUnitsDelete(true));
document.addEventListener('keyup', (event) => this.#onKeyUp(event));
document.addEventListener('exportToFile', () => this.exportToFile());
document.addEventListener('importFromFile', () => this.importFromFile());
document.addEventListener('contactsUpdated', (e: CustomEvent) => { this.#requestDetectionUpdate = true });
document.addEventListener('commandModeOptionsChanged', () => { Object.values(this.#units).forEach((unit: Unit) => unit.updateVisibility()) });
document.addEventListener('selectedUnitsChangeSpeed', (e: any) => { this.selectedUnitsChangeSpeed(e.detail.type) });
document.addEventListener('keyup', (event) => this.#onKeyUp(event));
document.addEventListener('paste', () => this.pasteUnits());
document.addEventListener('selectedUnitsChangeAltitude', (e: any) => { this.selectedUnitsChangeAltitude(e.detail.type) });
document.addEventListener('selectedUnitsChangeSpeed', (e: any) => { this.selectedUnitsChangeSpeed(e.detail.type) });
document.addEventListener('unitDeselection', (e: CustomEvent) => this.#onUnitDeselection(e.detail));
document.addEventListener('unitSelection', (e: CustomEvent) => this.#onUnitSelection(e.detail));
this.#slowDeleteDialog = new Dialog( "slow-delete-dialog" );
}
/**
@ -638,7 +643,7 @@ export class UnitsManager {
try {
groundElevation = parseFloat(response);
} catch {
console.log("Simulate fire fight: could not retrieve ground elevation")
console.warn("Simulate fire fight: could not retrieve ground elevation")
}
for (let idx in selectedUnits) {
selectedUnits[idx].simulateFireFight(latlng, groundElevation);
@ -754,14 +759,24 @@ export class UnitsManager {
return;
}
var immediate = false;
if (selectedUnits.length > 20)
immediate = confirm(`You are trying to delete ${selectedUnits.length} units, do you want to delete them immediately? This may cause lag for players.`)
for (let idx in selectedUnits) {
selectedUnits[idx].delete(explosion, immediate);
const doDelete = (explosion = false, immediate = false) => {
const selectedUnits = this.getSelectedUnits();
for (let idx in selectedUnits) {
selectedUnits[idx].delete(explosion, immediate);
}
this.#showActionMessage(selectedUnits, `deleted`);
}
this.#showActionMessage(selectedUnits, `deleted`);
if (selectedUnits.length >= DELETE_SLOW_THRESHOLD)
this.#showSlowDeleteDialog(selectedUnits).then((action:any) => {
if (action === "delete-slow")
doDelete(explosion, false);
else if (action === "delete-immediate")
doDelete(explosion, true);
})
else
doDelete(explosion);
}
/** Compute the destinations of every unit in the selected units. This function preserves the relative positions of the units, and rotates the whole formation by rotation.
@ -1083,4 +1098,32 @@ export class UnitsManager {
else if (units.length > 1)
(getApp().getPopupsManager().get("infoPopup") as Popup).setText(`${units[0].getUnitName()} and ${units.length - 1} other units ${message}`);
}
#showSlowDeleteDialog(selectedUnits:Unit[]) {
let button:HTMLButtonElement | null = null;
const deletionTime = Math.round( selectedUnits.length * DELETE_CYCLE_TIME ).toString();
const dialog = this.#slowDeleteDialog;
const element = dialog.getElement();
const listener = (ev:MouseEvent) => {
if (ev.target instanceof HTMLButtonElement && ev.target.matches("[data-action]"))
button = ev.target;
}
element.querySelectorAll(".deletion-count").forEach( el => el.innerHTML = selectedUnits.length.toString() );
element.querySelectorAll(".deletion-time").forEach( el => el.innerHTML = deletionTime );
dialog.show();
return new Promise((resolve) => {
element.addEventListener("click", listener);
const interval = setInterval(() => {
if (button instanceof HTMLButtonElement ) {
clearInterval(interval);
dialog.hide();
element.removeEventListener("click", listener);
resolve( button.getAttribute("data-action") );
}
}, 250);
});
}
}

View File

@ -304,4 +304,27 @@
<button class="ol-button-apply" data-on-click="applycommandModeOptions">Apply</button>
<button class="ol-button-close" data-on-click="closeDialog">Close</button>
</div>
</div>
</div>
<div id="slow-delete-dialog" class="ol-panel ol-dialog hide" oncontextmenu="return false;">
<div class="ol-dialog-header">
<h3 id="unit-name">Confirm deletion method</h3>
</div>
<div class="ol-dialog-content">
<p>You are trying to delete a large amount of units (<span class="deletion-count"></span>), which can cause the server to lag for players.</p>
<p>You may:
<ul>
<li>delete in batches (less lag but Olympus cannot process any additional orders until<br /> all units have been deleted);</li>
<li>delete immediately (you can continue to give Olympus orders but players may<br />experience lag while this happens);</li>
<li>cancel this instruction.</li>
</ul></p>
</div>
<div class="ol-dialog-footer ol-group">
<button data-action="delete-slow">Delete in batches (~<span class="deletion-time"></span>s)</button>
<button data-action="delete-immediate">Delete immediately</button>
<button data-action="delete-cancel">Cancel</button>
</div>
</div>