mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Split client into frontend website and server
This commit is contained in:
20
frontend/website/plugins/databasemanager/.vscode/launch.json
vendored
Normal file
20
frontend/website/plugins/databasemanager/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Attach to Chrome",
|
||||
"port": 9222,
|
||||
"urlFilter": "http://localhost:3000/*",
|
||||
"request": "attach",
|
||||
"type": "chrome",
|
||||
"webRoot": "${workspaceFolder}../../public/",
|
||||
"sourceMapPathOverrides": {
|
||||
"src/*": "src/*"
|
||||
},
|
||||
"preLaunchTask": "start"
|
||||
}
|
||||
]
|
||||
}
|
||||
13
frontend/website/plugins/databasemanager/.vscode/tasks.json
vendored
Normal file
13
frontend/website/plugins/databasemanager/.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "start",
|
||||
"type": "shell",
|
||||
"command": "npm run start",
|
||||
"isBackground": true
|
||||
}
|
||||
]
|
||||
}
|
||||
5
frontend/website/plugins/databasemanager/copy.bat
Normal file
5
frontend/website/plugins/databasemanager/copy.bat
Normal file
@@ -0,0 +1,5 @@
|
||||
mkdir .\\..\\..\\public\\plugins\\databasemanager
|
||||
|
||||
copy .\\index.js .\\..\\..\\public\\plugins\\databasemanager\\index.js
|
||||
copy .\\plugin.json .\\..\\..\\public\\plugins\\databasemanager\\plugin.json
|
||||
copy .\\style.css .\\..\\..\\public\\plugins\\databasemanager\\style.css
|
||||
1
frontend/website/plugins/databasemanager/index.js
Normal file
1
frontend/website/plugins/databasemanager/index.js
Normal file
File diff suppressed because one or more lines are too long
32
frontend/website/plugins/databasemanager/package.json
Normal file
32
frontend/website/plugins/databasemanager/package.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "DatabaseManagerPlugin",
|
||||
"version": "v0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "browserify ./src/index.ts -p [ tsify --noImplicitAny] > index.js && copy.bat",
|
||||
"build-release": "browserify ./src/index.ts -p [ tsify --noImplicitAny] -p [ tinyify ] > index.js && copy.bat",
|
||||
"start": "npm run copy & concurrently --kill-others \"npm run watch\"",
|
||||
"copy": "copy.bat",
|
||||
"watch": "watchify ./src/index.ts --debug -o ../../public/plugins/databasemanager/index.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js']"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.21.4",
|
||||
"@types/node": "^18.16.1",
|
||||
"@types/sortablejs": "^1.15.0",
|
||||
"babelify": "^10.0.0",
|
||||
"browserify": "^17.0.0",
|
||||
"concurrently": "^7.6.0",
|
||||
"cp": "^0.2.0",
|
||||
"esmify": "^2.1.1",
|
||||
"nodemon": "^2.0.20",
|
||||
"requirejs": "^2.3.6",
|
||||
"sortablejs": "^1.15.0",
|
||||
"tinyify": "^4.0.0",
|
||||
"tsify": "^5.0.4",
|
||||
"tslib": "latest",
|
||||
"typescript": "^4.9.4",
|
||||
"usng.js": "^0.4.5",
|
||||
"watchify": "^4.0.0"
|
||||
}
|
||||
}
|
||||
6
frontend/website/plugins/databasemanager/plugin.json
Normal file
6
frontend/website/plugins/databasemanager/plugin.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "Control Tip Plugin",
|
||||
"version": "0.0.1",
|
||||
"description": "This plugin shows useful control tips on the right side of the screen. The tips change dynamically depending on what the user does",
|
||||
"author": "Peekaboo"
|
||||
}
|
||||
110
frontend/website/plugins/databasemanager/src/airuniteditor.ts
Normal file
110
frontend/website/plugins/databasemanager/src/airuniteditor.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import { LoadoutBlueprint, UnitBlueprint } from "interfaces";
|
||||
import { UnitEditor } from "./uniteditor";
|
||||
import { LoadoutEditor } from "./loadouteditor";
|
||||
import { addCheckboxInput, addDropdownInput, addLoadoutsScroll, addNewElementInput, addStringInput } from "./utils";
|
||||
|
||||
/** Database editor for Air Units, both Aircraft and Helicopter since they are identical in terms of datbase entries.
|
||||
*
|
||||
*/
|
||||
export class AirUnitEditor extends UnitEditor {
|
||||
|
||||
#loadoutEditor: LoadoutEditor | null = null;
|
||||
|
||||
constructor(contentDiv1: HTMLElement, contentDiv2: HTMLElement, contentDiv3: HTMLElement) {
|
||||
super(contentDiv1, contentDiv2, contentDiv3);
|
||||
|
||||
/* The loadout editor allows to edit the loadout (who could have thought eh?) */
|
||||
this.#loadoutEditor = new LoadoutEditor(this.contentDiv3);
|
||||
|
||||
/* Refresh the loadout editor if needed */
|
||||
this.contentDiv3.addEventListener("refresh", () => {
|
||||
if (this.visible)
|
||||
this.#loadoutEditor?.show();
|
||||
});
|
||||
}
|
||||
|
||||
/** Sets a unit blueprint as the currently active one
|
||||
*
|
||||
* @param blueprint The blueprint to edit
|
||||
*/
|
||||
setBlueprint(blueprint: UnitBlueprint) {
|
||||
this.blueprint = blueprint;
|
||||
|
||||
if (this.blueprint !== null) {
|
||||
this.contentDiv2.replaceChildren();
|
||||
|
||||
var title = document.createElement("label");
|
||||
title.innerText = "Unit properties";
|
||||
this.contentDiv2.appendChild(title);
|
||||
|
||||
addStringInput(this.contentDiv2, "Name", blueprint.name, "text", (value: string) => { blueprint.name = value; }, true);
|
||||
addStringInput(this.contentDiv2, "Label", blueprint.label, "text", (value: string) => { blueprint.label = value; });
|
||||
addStringInput(this.contentDiv2, "Short label", blueprint.shortLabel, "text", (value: string) => { blueprint.shortLabel = value; });
|
||||
addDropdownInput(this.contentDiv2, "Coalition", blueprint.coalition, ["", "blue", "red"], (value: string) => {blueprint.coalition = value; });
|
||||
addDropdownInput(this.contentDiv2, "Era", blueprint.era, ["WW2", "Early Cold War", "Mid Cold War", "Late Cold War", "Modern"], (value: string) => {blueprint.era = value; });
|
||||
addStringInput(this.contentDiv2, "Filename", blueprint.filename ?? "", "text", (value: string) => { blueprint.filename = value; });
|
||||
addStringInput(this.contentDiv2, "Cost", String(blueprint.cost) ?? "", "number", (value: string) => { blueprint.cost = parseFloat(value); });
|
||||
addCheckboxInput(this.contentDiv2, "Can target point", blueprint.canTargetPoint ?? false, (value: boolean) => {blueprint.canTargetPoint = value;})
|
||||
addStringInput(this.contentDiv2, "Description", blueprint.description ?? "", "text", (value: string) => {blueprint.description = value; });
|
||||
addStringInput(this.contentDiv2, "Tags", blueprint.tags ?? "", "text", (value: string) => {blueprint.tags = value; });
|
||||
|
||||
/* Add a scrollable list of loadouts that the user can edit */
|
||||
var title = document.createElement("label");
|
||||
title.innerText = "Loadouts";
|
||||
this.contentDiv2.appendChild(title);
|
||||
addLoadoutsScroll(this.contentDiv2, blueprint.loadouts ?? [], (loadout: LoadoutBlueprint) => {
|
||||
this.#loadoutEditor?.setLoadout(loadout);
|
||||
this.#loadoutEditor?.show();
|
||||
});
|
||||
addNewElementInput(this.contentDiv2, (ev: MouseEvent, input: HTMLInputElement) => { this.addLoadout(input.value); });
|
||||
|
||||
this.#loadoutEditor?.hide();
|
||||
}
|
||||
}
|
||||
|
||||
/** Add a new empty blueprint
|
||||
*
|
||||
* @param key Blueprint key
|
||||
*/
|
||||
addBlueprint(key: string) {
|
||||
if (this.database != null) {
|
||||
this.database.blueprints[key] = {
|
||||
name: key,
|
||||
coalition: "",
|
||||
label: "",
|
||||
shortLabel: "",
|
||||
era: "",
|
||||
loadouts: [],
|
||||
enabled: true
|
||||
}
|
||||
this.show();
|
||||
this.setBlueprint(this.database.blueprints[key]);
|
||||
}
|
||||
}
|
||||
|
||||
/** Add a new empty loadout to the currently active blueprint
|
||||
*
|
||||
* @param loadoutName The name of the new loadout
|
||||
*/
|
||||
addLoadout(loadoutName: string) {
|
||||
if (loadoutName && this.blueprint !== null) {
|
||||
this.blueprint.loadouts?.push({
|
||||
name: loadoutName,
|
||||
code: "",
|
||||
fuel: 1,
|
||||
items: [],
|
||||
roles: [],
|
||||
enabled: true
|
||||
})
|
||||
this.setBlueprint(this.blueprint);
|
||||
}
|
||||
}
|
||||
|
||||
/** Hide the editor
|
||||
*
|
||||
*/
|
||||
hide() {
|
||||
super.hide();
|
||||
this.#loadoutEditor?.hide();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,424 @@
|
||||
import { OlympusPlugin, UnitBlueprint } from "interfaces";
|
||||
import { AirUnitEditor } from "./airuniteditor";
|
||||
import { OlympusApp } from "olympusapp";
|
||||
import { GroundUnitEditor } from "./grounduniteditor";
|
||||
import { PrimaryToolbar } from "toolbars/primarytoolbar";
|
||||
import { NavyUnitEditor } from "./navyuniteditor";
|
||||
|
||||
/** Database Manager
|
||||
*
|
||||
* This database provides a user interface to allow easier and convenient unit databases manipulation. It allows to edit all the fields of the units databases, save them
|
||||
* on the server, and restore the defaults.
|
||||
*
|
||||
* TODO:
|
||||
* Add ability to manage liveries
|
||||
*
|
||||
*/
|
||||
|
||||
export class DatabaseManagerPlugin implements OlympusPlugin {
|
||||
#app!: OlympusApp;
|
||||
|
||||
#element: HTMLElement;
|
||||
#mainContentContainer: HTMLElement;
|
||||
#contentDiv1: HTMLElement;
|
||||
#contentDiv2: HTMLElement;
|
||||
#contentDiv3: HTMLElement;
|
||||
|
||||
/* Upper tab buttons */
|
||||
#button1: HTMLButtonElement;
|
||||
#button2: HTMLButtonElement;
|
||||
#button3: HTMLButtonElement;
|
||||
#button4: HTMLButtonElement;
|
||||
|
||||
/* Lower operation buttons */
|
||||
#button5: HTMLButtonElement;
|
||||
#button6: HTMLButtonElement;
|
||||
#button7: HTMLButtonElement;
|
||||
#button8: HTMLButtonElement;
|
||||
#button9: HTMLButtonElement;
|
||||
|
||||
/* Database editors */
|
||||
#aircraftEditor: AirUnitEditor;
|
||||
#helicopterEditor: AirUnitEditor;
|
||||
#groundUnitEditor: GroundUnitEditor;
|
||||
#navyUnitEditor: NavyUnitEditor;
|
||||
|
||||
constructor() {
|
||||
/* Create main HTML element */
|
||||
this.#element = document.createElement("div");
|
||||
this.#element.id = "database-manager-panel";
|
||||
this.#element.oncontextmenu = () => { return false; }
|
||||
this.#element.classList.add("ol-dialog");
|
||||
document.body.appendChild(this.#element);
|
||||
|
||||
/* Start hidden */
|
||||
this.toggle(false);
|
||||
|
||||
/* Create the top tab buttons container and buttons */
|
||||
let topButtonContainer = document.createElement("div");
|
||||
|
||||
this.#button1 = document.createElement("button");
|
||||
this.#button1.classList.add("tab-button");
|
||||
this.#button1.textContent = "Aircraft database";
|
||||
this.#button1.onclick = () => { this.#hideAll(); this.#aircraftEditor.show(); this.#button1.classList.add("selected"); };
|
||||
topButtonContainer.appendChild(this.#button1);
|
||||
|
||||
this.#button2 = document.createElement("button");
|
||||
this.#button2.classList.add("tab-button");
|
||||
this.#button2.textContent = "Helicopter database";
|
||||
this.#button2.onclick = () => { this.#hideAll(); this.#helicopterEditor.show(); this.#button2.classList.add("selected"); };
|
||||
topButtonContainer.appendChild(this.#button2);
|
||||
|
||||
this.#button3 = document.createElement("button");
|
||||
this.#button3.classList.add("tab-button");
|
||||
this.#button3.textContent = "Ground Unit database";
|
||||
this.#button3.onclick = () => { this.#hideAll(); this.#groundUnitEditor.show(); this.#button3.classList.add("selected"); };
|
||||
topButtonContainer.appendChild(this.#button3);
|
||||
|
||||
this.#button4 = document.createElement("button");
|
||||
this.#button4.classList.add("tab-button");
|
||||
this.#button4.textContent = "Navy Unit database";
|
||||
this.#button4.onclick = () => { this.#hideAll(); this.#navyUnitEditor.show(); this.#button4.classList.add("selected"); };
|
||||
topButtonContainer.appendChild(this.#button4);
|
||||
|
||||
this.#element.appendChild(topButtonContainer);
|
||||
|
||||
/* Create the container for the database editor elements and the elements themselves */
|
||||
this.#mainContentContainer = document.createElement("div");
|
||||
this.#mainContentContainer.classList.add("dm-container");
|
||||
this.#element.appendChild(this.#mainContentContainer);
|
||||
|
||||
this.#contentDiv1 = document.createElement("div");
|
||||
this.#contentDiv1.classList.add("dm-content-container", "ol-scrollable");
|
||||
this.#mainContentContainer.appendChild(this.#contentDiv1);
|
||||
|
||||
this.#contentDiv2 = document.createElement("div");
|
||||
this.#contentDiv2.classList.add("dm-content-container", "ol-scrollable");
|
||||
this.#mainContentContainer.appendChild(this.#contentDiv2);
|
||||
|
||||
this.#contentDiv3 = document.createElement("div");
|
||||
this.#contentDiv3.classList.add("dm-content-container", "ol-scrollable");
|
||||
this.#mainContentContainer.appendChild(this.#contentDiv3);
|
||||
|
||||
/* Create the database editors, which use the three divs created before */
|
||||
this.#aircraftEditor = new AirUnitEditor(this.#contentDiv1, this.#contentDiv2, this.#contentDiv3);
|
||||
this.#helicopterEditor = new AirUnitEditor(this.#contentDiv1, this.#contentDiv2, this.#contentDiv3);
|
||||
this.#groundUnitEditor = new GroundUnitEditor(this.#contentDiv1, this.#contentDiv2, this.#contentDiv3);
|
||||
this.#navyUnitEditor = new NavyUnitEditor(this.#contentDiv1, this.#contentDiv2, this.#contentDiv3);
|
||||
|
||||
/* Create the bottom buttons container. These buttons allow to save, restore, reset, and discard the changes */
|
||||
let bottomButtonContainer = document.createElement("div");
|
||||
|
||||
this.#button5 = document.createElement("button");
|
||||
this.#button5.textContent = "Save";
|
||||
this.#button5.title = "Save the changes on the server"
|
||||
this.#button5.onclick = () => { this.#saveDatabases();};
|
||||
bottomButtonContainer.appendChild(this.#button5);
|
||||
|
||||
this.#button6 = document.createElement("button");
|
||||
this.#button6.textContent = "Discard";
|
||||
this.#button6.title = "Discard all changes and reload the database from the server";
|
||||
this.#button6.onclick = () => { this.#loadDatabases(); };
|
||||
bottomButtonContainer.appendChild(this.#button6);
|
||||
|
||||
this.#button7 = document.createElement("button");
|
||||
this.#button7.textContent = "Reset defaults";
|
||||
this.#button7.onclick = () => { this.#resetToDefaultDatabases(); };
|
||||
this.#button7.title = "Reset the databases to the default values";
|
||||
bottomButtonContainer.appendChild(this.#button7);
|
||||
|
||||
this.#button8 = document.createElement("button");
|
||||
this.#button8.textContent = "Restore previous";
|
||||
this.#button8.onclick = () => { this.#restoreToPreviousDatabases(); };
|
||||
this.#button8.title = "Restore the previously saved databases. Use this if you saved a database by mistake.";
|
||||
bottomButtonContainer.appendChild(this.#button8);
|
||||
|
||||
this.#button9 = document.createElement("button");
|
||||
this.#button9.textContent = "Close";
|
||||
this.#button9.title = "Close the Database Manager"
|
||||
this.#button9.onclick = () => { this.toggle(false); };
|
||||
bottomButtonContainer.appendChild(this.#button9);
|
||||
|
||||
this.#element.appendChild(bottomButtonContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns The name of the plugin
|
||||
*/
|
||||
getName() {
|
||||
return "Database Control Plugin"
|
||||
}
|
||||
|
||||
/** Initialize the plugin
|
||||
*
|
||||
* @param app The OlympusApp singleton
|
||||
* @returns True if successfull
|
||||
*/
|
||||
initialize(app: any) {
|
||||
this.#app = app;
|
||||
|
||||
const contextManager = this.#app.getContextManager();
|
||||
contextManager.add( "databaseManager", {
|
||||
"allowUnitCopying": false,
|
||||
"allowUnitPasting": false,
|
||||
"useSpawnMenu": false,
|
||||
"useUnitControlPanel": false,
|
||||
"useUnitInfoPanel": false
|
||||
});
|
||||
|
||||
/* Load the databases and initialize the editors */
|
||||
this.#loadDatabases();
|
||||
|
||||
/* Add a button to the main Olympus App to allow the users to open the dialog */
|
||||
var mainButtonDiv = document.createElement("div");
|
||||
var mainButton = document.createElement("button");
|
||||
mainButton.textContent = "Database manager";
|
||||
mainButtonDiv.appendChild(mainButton);
|
||||
var toolbar: PrimaryToolbar = this.#app?.getToolbarsManager().get("primaryToolbar") as PrimaryToolbar;
|
||||
var elements = toolbar.getMainDropdown().getOptionElements();
|
||||
var arr = Array.prototype.slice.call(elements);
|
||||
arr.splice(arr.length - 3, 0, mainButtonDiv);
|
||||
toolbar.getMainDropdown().setOptionsElements(arr);
|
||||
mainButton.onclick = () => {
|
||||
toolbar.getMainDropdown().close();
|
||||
if (this.#app?.getMissionManager().getCommandModeOptions().commandMode === "Game master")
|
||||
this.toggle();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns The main container element
|
||||
*/
|
||||
getElement() {
|
||||
return this.#element;
|
||||
}
|
||||
|
||||
/** Toggles the visibility of the dialog
|
||||
*
|
||||
* @param bool Force a specific visibility state
|
||||
*/
|
||||
toggle(bool?: boolean) {
|
||||
if (bool)
|
||||
this.getElement().classList.toggle("hide", !bool);
|
||||
else
|
||||
this.getElement().classList.toggle("hide");
|
||||
|
||||
if ( this.#app )
|
||||
this.#app.getContextManager().setContext( this.getElement().classList.contains("hide") ? "olympus" : "databaseManager" );
|
||||
}
|
||||
|
||||
/** Hide all the editors
|
||||
*
|
||||
*/
|
||||
#hideAll() {
|
||||
this.#aircraftEditor.hide();
|
||||
this.#helicopterEditor.hide();
|
||||
this.#groundUnitEditor.hide();
|
||||
this.#navyUnitEditor.hide();
|
||||
|
||||
this.#button1.classList.remove("selected");
|
||||
this.#button2.classList.remove("selected");
|
||||
this.#button3.classList.remove("selected");
|
||||
this.#button4.classList.remove("selected");
|
||||
}
|
||||
|
||||
/** Load the databases from the app to the editor. Note, this does not reload the databases from the server to the app
|
||||
*
|
||||
*/
|
||||
#loadDatabases() {
|
||||
var aircraftDatabase = this.#app?.getAircraftDatabase();
|
||||
if (aircraftDatabase != null)
|
||||
this.#aircraftEditor.setDatabase(aircraftDatabase);
|
||||
|
||||
var helicopterDatabase = this.#app?.getHelicopterDatabase();
|
||||
if (helicopterDatabase != null)
|
||||
this.#helicopterEditor.setDatabase(helicopterDatabase);
|
||||
|
||||
var groundUnitDatabase = this.#app?.getGroundUnitDatabase();
|
||||
if (groundUnitDatabase != null)
|
||||
this.#groundUnitEditor.setDatabase(groundUnitDatabase);
|
||||
|
||||
var navyUnitDatabase = this.#app?.getNavyUnitDatabase();
|
||||
if (navyUnitDatabase != null)
|
||||
this.#navyUnitEditor.setDatabase(navyUnitDatabase);
|
||||
|
||||
this.#hideAll();
|
||||
this.#aircraftEditor.show();
|
||||
this.#button1.classList.add("selected");
|
||||
}
|
||||
|
||||
/** Save the databases on the server and reloads it to apply the changes
|
||||
*
|
||||
*/
|
||||
#saveDatabases() {
|
||||
var aircraftDatabase = this.#aircraftEditor.getDatabase();
|
||||
if (aircraftDatabase){
|
||||
this.#uploadDatabase(aircraftDatabase, "aircraftdatabase", "Aircraft database", () => {
|
||||
var helicopterDatabase = this.#helicopterEditor.getDatabase();
|
||||
if (helicopterDatabase) {
|
||||
this.#uploadDatabase(helicopterDatabase, "helicopterDatabase", "Helicopter database", () => {
|
||||
var groundUnitDatabase = this.#groundUnitEditor.getDatabase();
|
||||
if (groundUnitDatabase) {
|
||||
this.#uploadDatabase(groundUnitDatabase, "groundUnitDatabase", "Ground Unit database", () => {
|
||||
var navyUnitDatabase = this.#navyUnitEditor.getDatabase();
|
||||
if (navyUnitDatabase) {
|
||||
this.#uploadDatabase(navyUnitDatabase, "navyUnitDatabase", "Navy Unit database", () => {
|
||||
this.#app?.getAircraftDatabase().load(() => {});
|
||||
this.#app?.getHelicopterDatabase().load(() => {});
|
||||
this.#app?.getGroundUnitDatabase().load(() => {});
|
||||
this.#app?.getNavyUnitDatabase().load(() => {});
|
||||
|
||||
this.#app?.getServerManager().reloadDatabases(() => {
|
||||
this.#app?.getPopupsManager().get("infoPopup")?.setText("Olympus core databases reloaded");
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** Resets the databases to the default values
|
||||
*
|
||||
*/
|
||||
#resetToDefaultDatabases() {
|
||||
this.#resetToDefaultDatabase("aircraftdatabase", "Aircraft database", () => {
|
||||
this.#app?.getAircraftDatabase().load(() => {
|
||||
this.#resetToDefaultDatabase("helicopterdatabase", "Helicopter database", () => {
|
||||
this.#app?.getHelicopterDatabase().load(() => {
|
||||
this.#resetToDefaultDatabase("groundunitdatabase", "Ground Unit database", () => {
|
||||
this.#app?.getGroundUnitDatabase().load(() => {
|
||||
this.#resetToDefaultDatabase("navyunitdatabase", "Navy Unit database", () => {
|
||||
this.#app?.getNavyUnitDatabase().load(() => {
|
||||
this.#loadDatabases();
|
||||
|
||||
this.#app?.getServerManager().reloadDatabases(() => {
|
||||
this.#app?.getPopupsManager().get("infoPopup")?.setText("Olympus core databases reloaded");
|
||||
})
|
||||
|
||||
this.#hideAll();
|
||||
this.#aircraftEditor.show();
|
||||
this.#button1.classList.add("selected");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/** Restores the databases to the previous saved values. This is useful if you saved the databases by mistake and want to undo the error.
|
||||
*
|
||||
*/
|
||||
#restoreToPreviousDatabases() {
|
||||
this.#restoreToPreviousDatabase("aircraftdatabase", "Aircraft database", () => {
|
||||
this.#app?.getAircraftDatabase().load(() => {
|
||||
this.#restoreToPreviousDatabase("helicopterdatabase", "Helicopter database", () => {
|
||||
this.#app?.getHelicopterDatabase().load(() => {
|
||||
this.#restoreToPreviousDatabase("groundunitdatabase", "Ground Unit database", () => {
|
||||
this.#app?.getGroundUnitDatabase().load(() => {
|
||||
this.#restoreToPreviousDatabase("navyunitdatabase", "Navy Unit database", () => {
|
||||
this.#app?.getNavyUnitDatabase().load(() => {
|
||||
this.#loadDatabases();
|
||||
|
||||
this.#app?.getServerManager().reloadDatabases(() => {
|
||||
this.#app?.getPopupsManager().get("infoPopup")?.setText("Olympus core databases reloaded");
|
||||
})
|
||||
|
||||
this.#hideAll();
|
||||
this.#aircraftEditor.show();
|
||||
this.#button1.classList.add("selected");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/** Upload a single database to the server
|
||||
*
|
||||
* @param database The database
|
||||
* @param name The name of the database as it will be saved on the server
|
||||
* @param label A label used in the info popup
|
||||
*/
|
||||
#uploadDatabase(database: { blueprints: { [key: string]: UnitBlueprint } }, name: string, label: string, callback: CallableFunction) {
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.open("PUT", "/api/databases/save/units/" + name);
|
||||
xmlHttp.setRequestHeader("Content-Type", "application/json");
|
||||
xmlHttp.onload = (res: any) => {
|
||||
if (xmlHttp.status == 200) {
|
||||
this.#app?.getPopupsManager().get("infoPopup")?.setText(label + " saved successfully");
|
||||
callback();
|
||||
}
|
||||
else {
|
||||
this.#app?.getPopupsManager().get("infoPopup")?.setText("An error has occurred while saving the " + label);
|
||||
}
|
||||
};
|
||||
xmlHttp.onerror = (res: any) => {
|
||||
this.#app?.getPopupsManager().get("infoPopup")?.setText("An error has occurred while saving the " + label);
|
||||
}
|
||||
xmlHttp.send(JSON.stringify(database));
|
||||
}
|
||||
|
||||
/** Resets a database to its default values on the server. NOTE: this only resets the database on the server, it will not reload it in the app.
|
||||
*
|
||||
* @param name The name of the database as it is saved on the server
|
||||
* @param label A label used in the info popup
|
||||
* @param callback Called when the operation is completed
|
||||
*/
|
||||
#resetToDefaultDatabase(name: string, label: string, callback: CallableFunction) {
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.open("PUT", "/api/databases/reset/units/" + name);
|
||||
xmlHttp.setRequestHeader("Content-Type", "application/json");
|
||||
xmlHttp.onload = (res: any) => {
|
||||
if (xmlHttp.status == 200) {
|
||||
this.#app?.getPopupsManager().get("infoPopup")?.setText(label + " reset successfully");
|
||||
callback();
|
||||
}
|
||||
else {
|
||||
this.#app?.getPopupsManager().get("infoPopup")?.setText("An error has occurred while resetting the " + label);
|
||||
}
|
||||
};
|
||||
xmlHttp.onerror = (res: any) => {
|
||||
this.#app?.getPopupsManager().get("infoPopup")?.setText("An error has occurred while resetting the " + label)
|
||||
}
|
||||
xmlHttp.send("");
|
||||
}
|
||||
|
||||
/** Restores a database to its previously saved values on the server. NOTE: this only restores the database on the server, it will not reload it in the app.
|
||||
*
|
||||
* @param name The name of the database as it is saved on the server
|
||||
* @param label A label used in the info popup
|
||||
* @param callback Called when the operation is completed
|
||||
*/
|
||||
#restoreToPreviousDatabase(name: string, label: string, callback: CallableFunction) {
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.open("PUT", "/api/databases/restore/units/" + name);
|
||||
xmlHttp.setRequestHeader("Content-Type", "application/json");
|
||||
xmlHttp.onload = (res: any) => {
|
||||
if (xmlHttp.status == 200) {
|
||||
this.#app?.getPopupsManager().get("infoPopup")?.setText(label + " restored successfully");
|
||||
callback();
|
||||
}
|
||||
else {
|
||||
this.#app?.getPopupsManager().get("infoPopup")?.setText("An error has occurred while restoring the " + label);
|
||||
}
|
||||
};
|
||||
xmlHttp.onerror = (res: any) => {
|
||||
this.#app?.getPopupsManager().get("infoPopup")?.setText("An error has occurred while restoring the " + label)
|
||||
}
|
||||
xmlHttp.send("");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import { UnitBlueprint } from "interfaces";
|
||||
import { UnitEditor } from "./uniteditor";
|
||||
import { addCheckboxInput, addDropdownInput, addStringInput } from "./utils";
|
||||
|
||||
/** Database editor for ground units
|
||||
*
|
||||
*/
|
||||
export class GroundUnitEditor extends UnitEditor {
|
||||
#blueprint: UnitBlueprint | null = null;
|
||||
|
||||
constructor(contentDiv1: HTMLElement, contentDiv2: HTMLElement, contentDiv3: HTMLElement) {
|
||||
super(contentDiv1, contentDiv2, contentDiv3);
|
||||
}
|
||||
|
||||
/** Sets a unit blueprint as the currently active one
|
||||
*
|
||||
* @param blueprint The blueprint to edit
|
||||
*/
|
||||
setBlueprint(blueprint: UnitBlueprint) {
|
||||
this.#blueprint = blueprint;
|
||||
|
||||
if (this.#blueprint !== null) {
|
||||
this.contentDiv2.replaceChildren();
|
||||
|
||||
var title = document.createElement("label");
|
||||
title.innerText = "Unit properties";
|
||||
this.contentDiv2.appendChild(title);
|
||||
|
||||
addStringInput(this.contentDiv2, "Name", blueprint.name, "text", (value: string) => {blueprint.name = value; }, true);
|
||||
addStringInput(this.contentDiv2, "Label", blueprint.label, "text", (value: string) => {blueprint.label = value; });
|
||||
addStringInput(this.contentDiv2, "Short label", blueprint.shortLabel, "text", (value: string) => {blueprint.shortLabel = value; });
|
||||
addStringInput(this.contentDiv2, "Type", blueprint.type?? "", "text", (value: string) => {blueprint.type = value; });
|
||||
addStringInput(this.contentDiv2, "Unit when grouped", blueprint.unitWhenGrouped?? "", "text", (value: string) => {blueprint.unitWhenGrouped = value; });
|
||||
addDropdownInput(this.contentDiv2, "Coalition", blueprint.coalition, ["", "blue", "red"], (value: string) => {blueprint.coalition = value; });
|
||||
addDropdownInput(this.contentDiv2, "Era", blueprint.era, ["WW2", "Early Cold War", "Mid Cold War", "Late Cold War", "Modern"], (value: string) => {blueprint.era = value; });
|
||||
//addStringInput(this.contentDiv2, "Filename", blueprint.filename?? "", "text", (value: string) => {blueprint.filename = value; });
|
||||
addStringInput(this.contentDiv2, "Cost", String(blueprint.cost)?? "", "number", (value: string) => {blueprint.cost = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Acquisition range [m]", String(blueprint.acquisitionRange)?? "", "number", (value: string) => {blueprint.acquisitionRange = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Engagement range [m]", String(blueprint.engagementRange)?? "", "number", (value: string) => {blueprint.engagementRange = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Targeting range [m]", String(blueprint.targetingRange)?? "", "number", (value: string) => {blueprint.targetingRange = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Aim method range [m]", String(blueprint.aimMethodRange)?? "", "number", (value: string) => {blueprint.aimMethodRange = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Barrel height [m]", String(blueprint.barrelHeight)?? "", "number", (value: string) => {blueprint.barrelHeight = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Muzzle velocity [m/s]", String(blueprint.muzzleVelocity)?? "", "number", (value: string) => {blueprint.muzzleVelocity = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Aim time [s]", String(blueprint.aimTime)?? "", "number", (value: string) => {blueprint.aimTime = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Shots to fire", String(blueprint.shotsToFire)?? "", "number", (value: string) => {blueprint.shotsToFire = Math.round(parseFloat(value)); });
|
||||
addStringInput(this.contentDiv2, "Shots base interval [s]", String(blueprint.shotsBaseInterval)?? "", "number", (value: string) => {blueprint.shotsBaseInterval = Math.round(parseFloat(value)); });
|
||||
addStringInput(this.contentDiv2, "Shots base scatter [°]", String(blueprint.shotsBaseScatter)?? "", "number", (value: string) => {blueprint.shotsBaseScatter = Math.round(parseFloat(value)); });
|
||||
addStringInput(this.contentDiv2, "Alertness time constant [s]", String(blueprint.alertnessTimeConstant)?? "", "number", (value: string) => {blueprint.alertnessTimeConstant = Math.round(parseFloat(value)); });
|
||||
addCheckboxInput(this.contentDiv2, "Can target point", blueprint.canTargetPoint ?? false, (value: boolean) => {blueprint.canTargetPoint = value;})
|
||||
addCheckboxInput(this.contentDiv2, "Can rearm", blueprint.canRearm ?? false, (value: boolean) => {blueprint.canRearm = value;})
|
||||
addCheckboxInput(this.contentDiv2, "Can operate as AAA", blueprint.canAAA ?? false, (value: boolean) => {blueprint.canAAA = value;})
|
||||
addCheckboxInput(this.contentDiv2, "Indirect fire (e.g. mortar)", blueprint.indirectFire ?? false, (value: boolean) => {blueprint.indirectFire = value;})
|
||||
addStringInput(this.contentDiv2, "Description", blueprint.description ?? "", "text", (value: string) => {blueprint.description = value; });
|
||||
addStringInput(this.contentDiv2, "Tags", blueprint.tags ?? "", "text", (value: string) => {blueprint.tags = value; });
|
||||
addStringInput(this.contentDiv2, "Marker file", blueprint.markerFile ?? "", "text", (value: string) => {blueprint.markerFile = value; });
|
||||
}
|
||||
}
|
||||
|
||||
/** Add a new empty blueprint
|
||||
*
|
||||
* @param key Blueprint key
|
||||
*/
|
||||
addBlueprint(key: string) {
|
||||
if (this.database != null) {
|
||||
this.database.blueprints[key] = {
|
||||
name: key,
|
||||
coalition: "",
|
||||
label: "",
|
||||
shortLabel: "",
|
||||
era: "",
|
||||
enabled: true
|
||||
}
|
||||
this.show();
|
||||
this.setBlueprint(this.database.blueprints[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
5
frontend/website/plugins/databasemanager/src/index.ts
Normal file
5
frontend/website/plugins/databasemanager/src/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { DatabaseManagerPlugin } from "./databasemanagerplugin";
|
||||
|
||||
globalThis.getOlympusPlugin = () => {
|
||||
return new DatabaseManagerPlugin();
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import { LoadoutBlueprint } from "interfaces";
|
||||
import { addLoadoutItemsEditor, addStringInput, arrayToString, stringToArray } from "./utils";
|
||||
|
||||
/** The LoadoutEditor allows the user to edit a loadout
|
||||
*
|
||||
*/
|
||||
export class LoadoutEditor {
|
||||
#contentDiv: HTMLElement;
|
||||
#loadout: LoadoutBlueprint | null = null;
|
||||
#visible: boolean = false;
|
||||
|
||||
constructor(contentDiv: HTMLElement) {
|
||||
this.#contentDiv = contentDiv;
|
||||
this.#contentDiv.addEventListener("refresh", () => {
|
||||
if (this.#visible)
|
||||
this.show();
|
||||
})
|
||||
}
|
||||
|
||||
/** Set the loadout to edit
|
||||
*
|
||||
* @param loadout The loadout to edit
|
||||
*/
|
||||
setLoadout(loadout: LoadoutBlueprint) {
|
||||
this.#loadout = loadout;
|
||||
}
|
||||
|
||||
/** Show the editor
|
||||
*
|
||||
*/
|
||||
show() {
|
||||
this.#visible = true;
|
||||
this.#contentDiv.replaceChildren();
|
||||
|
||||
var title = document.createElement("label");
|
||||
title.innerText = "Loadout properties";
|
||||
this.#contentDiv.appendChild(title);
|
||||
|
||||
if (this.#loadout) {
|
||||
var loadout = this.#loadout;
|
||||
addStringInput(this.#contentDiv, "Name", loadout.name, "text", (value: string) => {loadout.name = value; this.#contentDiv.dispatchEvent(new Event("refresh"));});
|
||||
addStringInput(this.#contentDiv, "Code", loadout.code, "text", (value: string) => {loadout.code = value; });
|
||||
addStringInput(this.#contentDiv, "Roles", arrayToString(loadout.roles), "text", (value: string) => {loadout.roles = stringToArray(value);});
|
||||
addLoadoutItemsEditor(this.#contentDiv, this.#loadout);
|
||||
}
|
||||
}
|
||||
|
||||
/** Hide the editor
|
||||
*
|
||||
*/
|
||||
hide() {
|
||||
this.#visible = false;
|
||||
this.#contentDiv.replaceChildren();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import { UnitBlueprint } from "interfaces";
|
||||
import { UnitEditor } from "./uniteditor";
|
||||
import { addDropdownInput, addStringInput } from "./utils";
|
||||
|
||||
/** Database editor for navy units
|
||||
*
|
||||
*/
|
||||
export class NavyUnitEditor extends UnitEditor {
|
||||
#blueprint: UnitBlueprint | null = null;
|
||||
|
||||
constructor(contentDiv1: HTMLElement, contentDiv2: HTMLElement, contentDiv3: HTMLElement) {
|
||||
super(contentDiv1, contentDiv2, contentDiv3);
|
||||
}
|
||||
|
||||
/** Sets a unit blueprint as the currently active one
|
||||
*
|
||||
* @param blueprint The blueprint to edit
|
||||
*/
|
||||
setBlueprint(blueprint: UnitBlueprint) {
|
||||
this.#blueprint = blueprint;
|
||||
|
||||
if (this.#blueprint !== null) {
|
||||
this.contentDiv2.replaceChildren();
|
||||
|
||||
var title = document.createElement("label");
|
||||
title.innerText = "Unit properties";
|
||||
this.contentDiv2.appendChild(title);
|
||||
|
||||
addStringInput(this.contentDiv2, "Name", blueprint.name, "text", (value: string) => {blueprint.name = value; }, true);
|
||||
addStringInput(this.contentDiv2, "Label", blueprint.label, "text", (value: string) => {blueprint.label = value; });
|
||||
addStringInput(this.contentDiv2, "Short label", blueprint.shortLabel, "text", (value: string) => {blueprint.shortLabel = value; });
|
||||
addStringInput(this.contentDiv2, "Type", blueprint.type?? "", "text", (value: string) => {blueprint.type = value; });
|
||||
addDropdownInput(this.contentDiv2, "Coalition", blueprint.coalition, ["", "blue", "red"], (value: string) => {blueprint.coalition = value; });
|
||||
addDropdownInput(this.contentDiv2, "Era", blueprint.era, ["WW2", "Early Cold War", "Mid Cold War", "Late Cold War", "Modern"], (value: string) => {blueprint.era = value; });
|
||||
//addStringInput(this.contentDiv2, "Filename", blueprint.filename?? "", "text", (value: string) => {blueprint.filename = value; });
|
||||
addStringInput(this.contentDiv2, "Cost", String(blueprint.cost)?? "", "number", (value: string) => {blueprint.cost = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Barrel height [m]", String(blueprint.barrelHeight)?? "", "number", (value: string) => {blueprint.barrelHeight = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Muzzle velocity [m/s]", String(blueprint.muzzleVelocity)?? "", "number", (value: string) => {blueprint.muzzleVelocity = parseFloat(value); });
|
||||
}
|
||||
}
|
||||
|
||||
/** Add a new empty blueprint
|
||||
*
|
||||
* @param key Blueprint key
|
||||
*/
|
||||
addBlueprint(key: string) {
|
||||
if (this.database != null) {
|
||||
this.database.blueprints[key] = {
|
||||
name: key,
|
||||
coalition: "",
|
||||
label: "",
|
||||
shortLabel: "",
|
||||
era: "",
|
||||
enabled: true
|
||||
}
|
||||
this.show();
|
||||
this.setBlueprint(this.database.blueprints[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
117
frontend/website/plugins/databasemanager/src/uniteditor.ts
Normal file
117
frontend/website/plugins/databasemanager/src/uniteditor.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import { UnitBlueprint } from "interfaces";
|
||||
import { UnitDatabase } from "unit/databases/unitdatabase";
|
||||
import { addBlueprintsScroll, addNewElementInput } from "./utils";
|
||||
|
||||
/** Base abstract class of Unit database editors
|
||||
*
|
||||
*/
|
||||
export abstract class UnitEditor {
|
||||
blueprint: UnitBlueprint | null = null;
|
||||
database: {blueprints: {[key: string]: UnitBlueprint}} | null = null;
|
||||
visible: boolean = false;
|
||||
contentDiv1: HTMLElement;
|
||||
contentDiv2: HTMLElement;
|
||||
contentDiv3: HTMLElement;
|
||||
|
||||
constructor(contentDiv1: HTMLElement, contentDiv2: HTMLElement, contentDiv3: HTMLElement) {
|
||||
this.contentDiv1 = contentDiv1;
|
||||
this.contentDiv2 = contentDiv2;
|
||||
this.contentDiv3 = contentDiv3;
|
||||
|
||||
/* Refresh the list of units if it changes */
|
||||
this.contentDiv1.addEventListener("refresh", () => {
|
||||
if (this.visible)
|
||||
this.show();
|
||||
})
|
||||
|
||||
/* If the unit properties or loadout are edited, reload the editor */
|
||||
this.contentDiv2.addEventListener("refresh", () => {
|
||||
if (this.visible) {
|
||||
if (this.blueprint !== null)
|
||||
this.setBlueprint(this.blueprint);
|
||||
}
|
||||
});
|
||||
|
||||
this.contentDiv3.addEventListener("refresh", () => {
|
||||
if (this.visible) {
|
||||
if (this.blueprint !== null)
|
||||
this.setBlueprint(this.blueprint);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param database The database that the editor will operate on
|
||||
*/
|
||||
setDatabase(database: UnitDatabase) {
|
||||
this.database = JSON.parse(JSON.stringify({blueprints: database.getBlueprints(true)}));
|
||||
}
|
||||
|
||||
/** Show the editor
|
||||
* @param filter String filter
|
||||
*/
|
||||
show(filter: string = "") {
|
||||
this.visible = true;
|
||||
this.contentDiv1.replaceChildren();
|
||||
this.contentDiv2.replaceChildren();
|
||||
this.contentDiv3.replaceChildren();
|
||||
|
||||
/* Create the list of units. Each unit is clickable to activate the editor on it */
|
||||
if (this.database != null) {
|
||||
var title = document.createElement("label");
|
||||
title.innerText = "Units list";
|
||||
this.contentDiv1.appendChild(title);
|
||||
|
||||
var filterInput = document.createElement("input");
|
||||
filterInput.value = filter;
|
||||
this.contentDiv1.appendChild(filterInput);
|
||||
|
||||
filterInput.onchange = (e: Event) => {
|
||||
this.show((e.target as HTMLInputElement).value);
|
||||
}
|
||||
|
||||
this.addBlueprints(filter);
|
||||
}
|
||||
}
|
||||
|
||||
/** Hide the editor
|
||||
*
|
||||
*/
|
||||
hide() {
|
||||
this.visible = false;
|
||||
this.contentDiv1.replaceChildren();
|
||||
this.contentDiv2.replaceChildren();
|
||||
this.contentDiv3.replaceChildren();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns The edited database
|
||||
*/
|
||||
getDatabase() {
|
||||
return this.database;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param filter String filter
|
||||
*/
|
||||
addBlueprints(filter: string = "") {
|
||||
if (this.database) {
|
||||
addBlueprintsScroll(this.contentDiv1, this.database, filter, (key: string) => {
|
||||
if (this.database != null)
|
||||
this.setBlueprint(this.database.blueprints[key])
|
||||
});
|
||||
|
||||
addNewElementInput(this.contentDiv1, (ev: MouseEvent, input: HTMLInputElement) => {
|
||||
if (input.value != "")
|
||||
this.addBlueprint((input).value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* Abstract methods which will depend on the specific type of units */
|
||||
abstract setBlueprint(blueprint: UnitBlueprint): void;
|
||||
abstract addBlueprint(key: string): void;
|
||||
}
|
||||
297
frontend/website/plugins/databasemanager/src/utils.ts
Normal file
297
frontend/website/plugins/databasemanager/src/utils.ts
Normal file
@@ -0,0 +1,297 @@
|
||||
import { LoadoutBlueprint, LoadoutItemBlueprint, UnitBlueprint } from "interfaces";
|
||||
|
||||
/** This file contains a set of utility functions that are reused in the various editors and allows to declutter the classes
|
||||
*
|
||||
*/
|
||||
|
||||
/** Add a string input in the form of String: [ value ]
|
||||
*
|
||||
* @param div The HTMLElement that will contain the input
|
||||
* @param key The key of the input, which will be used as label
|
||||
* @param value The initial value of the input
|
||||
* @param type The type of the input, e.g. "Text" or "Number" as per html standard
|
||||
* @param callback Callback called when the user enters a new value
|
||||
* @param disabled If true, the input will be disabled and read only
|
||||
*/
|
||||
export function addStringInput(div: HTMLElement, key: string, value: string, type: string, callback: CallableFunction, disabled?: boolean) {
|
||||
var row = document.createElement("div");
|
||||
var dt = document.createElement("dt");
|
||||
var dd = document.createElement("dd");
|
||||
dt.innerText = key;
|
||||
var input = document.createElement("input");
|
||||
input.value = value;
|
||||
input.textContent = value;
|
||||
input.type = type?? "text";
|
||||
input.disabled = disabled?? false;
|
||||
input.onchange = () => callback(input.value);
|
||||
dd.appendChild(input);
|
||||
row.appendChild(dt);
|
||||
row.appendChild(dd);
|
||||
row.classList.add("input-row");
|
||||
div.appendChild(row);
|
||||
}
|
||||
|
||||
/** Add a dropdown (select) input
|
||||
*
|
||||
* @param div The HTMLElement that will contain the input
|
||||
* @param key The key of the input, which will be used as label
|
||||
* @param value The initial value of the input
|
||||
* @param options The dropdown options
|
||||
*/
|
||||
export function addDropdownInput(div: HTMLElement, key: string, value: string, options: string[], callback: CallableFunction, disabled?: boolean) {
|
||||
var row = document.createElement("div");
|
||||
var dt = document.createElement("dt");
|
||||
var dd = document.createElement("dd");
|
||||
dt.innerText = key;
|
||||
var select = document.createElement("select");
|
||||
options.forEach((option: string) => {
|
||||
var el = document.createElement("option");
|
||||
el.value = option;
|
||||
el.innerText = option;
|
||||
select.appendChild(el);
|
||||
});
|
||||
select.value = value;
|
||||
select.disabled = disabled?? false;
|
||||
select.onchange = () => callback(select.value);
|
||||
dd.appendChild(select);
|
||||
row.appendChild(dt);
|
||||
row.appendChild(dd);
|
||||
row.classList.add("input-row");
|
||||
div.appendChild(row);
|
||||
}
|
||||
|
||||
/** Add a checkbox input in the form of String: [ value ]
|
||||
*
|
||||
* @param div The HTMLElement that will contain the input
|
||||
* @param key The key of the input, which will be used as label
|
||||
* @param value The initial value of the input
|
||||
* @param callback Callback called when the user enters a new value
|
||||
* @param disabled If true, the input will be disabled and read only
|
||||
*/
|
||||
export function addCheckboxInput(div: HTMLElement, key: string, value: boolean, callback: CallableFunction, disabled?: boolean) {
|
||||
var row = document.createElement("div");
|
||||
var dt = document.createElement("dt");
|
||||
var dd = document.createElement("dd");
|
||||
dt.innerText = key;
|
||||
var input = document.createElement("input");
|
||||
input.checked = value;
|
||||
input.type = "checkbox";
|
||||
input.disabled = disabled?? false;
|
||||
input.onchange = () => callback(input.checked);
|
||||
dd.appendChild(input);
|
||||
row.appendChild(dt);
|
||||
row.appendChild(dd);
|
||||
row.classList.add("input-row");
|
||||
div.appendChild(row);
|
||||
}
|
||||
|
||||
/** Create a loadout items editor. This editor allows to add or remove loadout items, as well as changing their name and quantity
|
||||
*
|
||||
* @param div The HTMLElement that will contain the editor
|
||||
* @param loadout The loadout to edit
|
||||
*/
|
||||
export function addLoadoutItemsEditor(div: HTMLElement, loadout: LoadoutBlueprint) {
|
||||
var itemsEl = document.createElement("div");
|
||||
itemsEl.classList.add("dm-scroll-container", "dm-items-container");
|
||||
|
||||
/* Create a row for each loadout item to allow and change the name and quantity of the item itself */
|
||||
loadout.items.sort((a: LoadoutItemBlueprint, b: LoadoutItemBlueprint) => a.name.localeCompare(b.name, undefined, {sensitivity: 'base'}));
|
||||
loadout.items.forEach((item: LoadoutItemBlueprint, index: number) => {
|
||||
var rowDiv = document.createElement("div");
|
||||
|
||||
var nameLabel = document.createElement("label");
|
||||
nameLabel.innerText = "Name"
|
||||
rowDiv.appendChild(nameLabel);
|
||||
|
||||
var nameInput = document.createElement("input");
|
||||
rowDiv.appendChild(nameInput);
|
||||
nameInput.textContent = item.name;
|
||||
nameInput.value = item.name
|
||||
nameInput.onchange = () => { loadout.items[index].name = nameInput.value; }
|
||||
|
||||
var quantityLabel = document.createElement("label");
|
||||
quantityLabel.innerText = "Quantity"
|
||||
rowDiv.appendChild(quantityLabel);
|
||||
|
||||
var quantityInput = document.createElement("input");
|
||||
rowDiv.appendChild(quantityInput);
|
||||
quantityInput.textContent = String(item.quantity);
|
||||
quantityInput.value = String(item.quantity);
|
||||
quantityInput.type = "number";
|
||||
quantityInput.step = "1";
|
||||
quantityInput.onchange = () => { loadout.items[index].quantity = parseInt(quantityInput.value); }
|
||||
|
||||
/* This button allows to remove the item */
|
||||
var button = document.createElement("button");
|
||||
button.innerText = "X";
|
||||
button.onclick = () => {
|
||||
loadout.items.splice(index, 1);
|
||||
div.dispatchEvent(new Event("refresh"));
|
||||
}
|
||||
rowDiv.appendChild(button);
|
||||
|
||||
itemsEl.appendChild(rowDiv);
|
||||
})
|
||||
div.appendChild(itemsEl);
|
||||
|
||||
/* Button to add a new item to the loadout */
|
||||
var inputDiv = document.createElement("div");
|
||||
inputDiv.classList.add("dm-new-item-input");
|
||||
var button = document.createElement("button");
|
||||
button.innerText = "Add";
|
||||
inputDiv.appendChild(button);
|
||||
div.appendChild(inputDiv);
|
||||
|
||||
button.addEventListener("click", (ev: MouseEvent) => {
|
||||
loadout?.items.push({
|
||||
name: "",
|
||||
quantity: 1
|
||||
})
|
||||
div.dispatchEvent(new Event("refresh"));
|
||||
});
|
||||
}
|
||||
|
||||
/** Add a input and button to create a new element in a list. It uses a generic callback to actually add the element.
|
||||
*
|
||||
* @param div The HTMLElement that will contain the input and button
|
||||
* @param callback Callback called when the user clicks on "Add"
|
||||
*/
|
||||
export function addNewElementInput(div: HTMLElement, callback: CallableFunction) {
|
||||
var inputDiv = document.createElement("div");
|
||||
inputDiv.classList.add("dm-new-element-input");
|
||||
|
||||
var input = document.createElement("input");
|
||||
inputDiv.appendChild(input);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerText = "Add";
|
||||
button.addEventListener("click", (ev: MouseEvent) => callback(ev, input));
|
||||
inputDiv.appendChild(button);
|
||||
div.appendChild(inputDiv);
|
||||
}
|
||||
|
||||
/** Add a scrollable list of blueprints
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
export function addBlueprintsScroll(div: HTMLElement, database: {blueprints: {[key: string]: UnitBlueprint}}, filter: string, callback: CallableFunction) {
|
||||
var scrollDiv = document.createElement("div");
|
||||
scrollDiv.classList.add("dm-scroll-container");
|
||||
if (database !== null) {
|
||||
var blueprints: {[key: string]: UnitBlueprint} = database.blueprints;
|
||||
|
||||
for (let key of Object.keys(blueprints).sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'}))) {
|
||||
var addKey = true;
|
||||
if (filter !== "") {
|
||||
try {
|
||||
var blueprint = blueprints[key];
|
||||
addKey = eval(filter);
|
||||
} catch {
|
||||
console.error("An error has occurred evaluating the blueprint filter")
|
||||
}
|
||||
}
|
||||
|
||||
if (addKey) {
|
||||
var rowDiv = document.createElement("div");
|
||||
scrollDiv.appendChild(rowDiv);
|
||||
|
||||
let text = document.createElement("div");
|
||||
text.innerHTML = `<div>${key}</div> <div>${blueprints[key].label}</div>`;
|
||||
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);
|
||||
}
|
||||
|
||||
/** Add a scrollable list of loadouts
|
||||
*
|
||||
* @param div The HTMLElement that will contain the list
|
||||
* @param loadouts The loadouts that will be used to fill the list
|
||||
* @param callback Callback called when the user clicks on one of the elements
|
||||
*/
|
||||
export function addLoadoutsScroll(div: HTMLElement, loadouts: LoadoutBlueprint[], callback: CallableFunction) {
|
||||
var loadoutsEl = document.createElement("div");
|
||||
loadoutsEl.classList.add("dm-scroll-container", "dm-loadout-container")
|
||||
|
||||
loadouts.sort((a: LoadoutBlueprint, b: LoadoutBlueprint) => a.name.localeCompare(b.name, undefined, {sensitivity: 'base'}));
|
||||
loadouts.forEach((loadout: LoadoutBlueprint, index: number) => {
|
||||
var rowDiv = document.createElement("div");
|
||||
loadoutsEl.appendChild(rowDiv);
|
||||
|
||||
var text = document.createElement("label");
|
||||
text.textContent = loadout.name;
|
||||
text.onclick = () => { callback(loadout) };
|
||||
rowDiv.appendChild(text);
|
||||
|
||||
/* The "Empty loadout" can not be removed */
|
||||
if (loadout.name !== "Empty loadout") {
|
||||
let checkbox = document.createElement("input");
|
||||
checkbox.type = "checkbox";
|
||||
checkbox.checked = loadout.enabled;
|
||||
checkbox.onclick = () => {
|
||||
console.log(checkbox.checked);
|
||||
loadout.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 = () => {
|
||||
loadouts.splice(index, 1);
|
||||
div.dispatchEvent(new Event("refresh"));
|
||||
}
|
||||
rowDiv.appendChild(button);
|
||||
}
|
||||
});
|
||||
|
||||
div.appendChild(loadoutsEl);
|
||||
}
|
||||
|
||||
/** Converts an array of string into a single string like [val1, val2, val3]
|
||||
*
|
||||
* @param array The input array of strings
|
||||
* @returns The string
|
||||
*/
|
||||
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 ) ?? [];
|
||||
}
|
||||
295
frontend/website/plugins/databasemanager/style.css
Normal file
295
frontend/website/plugins/databasemanager/style.css
Normal file
@@ -0,0 +1,295 @@
|
||||
#database-manager-panel {
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
background-color: var(--background-steel) !important;
|
||||
z-index: 9999999;
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.dm-container {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.dm-container {
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
#database-manager-panel * {
|
||||
font-size: 13;
|
||||
font-family: 'Open Sans', sans-serif !important;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#database-manager-panel>div:first-child {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#database-manager-panel>div:last-child {
|
||||
display: flex;
|
||||
column-gap: 5px;
|
||||
align-items: center;
|
||||
justify-content: end;
|
||||
justify-items: end;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
#database-manager-panel>div:last-child>button {
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
||||
.dm-container {
|
||||
background-color: var(--background-grey);
|
||||
border: 2px solid #777777;
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
height: calc(100% - 64px - 5px);
|
||||
border-radius: 0px 5px 5px 5px;
|
||||
}
|
||||
|
||||
.dm-content-container {
|
||||
position: relative;
|
||||
margin: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 5px;
|
||||
max-height: 100%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.dm-content-container {
|
||||
height: calc(100% - 20px);
|
||||
}
|
||||
|
||||
.dm-content-container:nth-of-type(1) {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.dm-content-container:nth-of-type(2) {
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
.dm-content-container:nth-of-type(3) {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.dm-content-container {
|
||||
width: calc(100% - 20px);
|
||||
}
|
||||
|
||||
.dm-content-container:nth-of-type(1) {
|
||||
height: 30%;
|
||||
}
|
||||
|
||||
.dm-content-container:nth-of-type(2) {
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
.dm-content-container:nth-of-type(3) {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.dm-content-container>label {
|
||||
font-size: 18px !important;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.dm-scroll-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: scroll;
|
||||
max-height: 100%;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#database-manager-panel input {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.dm-scroll-container>div:nth-child(even) {
|
||||
background-color: gainsboro;
|
||||
}
|
||||
|
||||
.dm-scroll-container>div:nth-child(odd) {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.dm-scroll-container>div *:nth-child(1) {
|
||||
height: 100%;
|
||||
width: calc(100% - 25px);
|
||||
padding: 2px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.dm-scroll-container>div *:nth-child(1):hover {
|
||||
background-color: var(--accent-dark-blue);
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.blueprint-selected {
|
||||
background-color: var(--accent-light-blue) !important;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.dm-scroll-container>div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.dm-scroll-container>div>div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.dm-scroll-container>div>button {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.dm-scroll-container>div>div>div:nth-child(1) {
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.dm-scroll-container>div>div>div:nth-child(2) {
|
||||
overflow: hidden;
|
||||
text-wrap: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.input-row {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.dm-content-container label {
|
||||
width: 100%;
|
||||
}
|
||||
.input-row {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.input-row>dt {
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.input-row>dd {
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.input-row>dd>* {
|
||||
width: 100%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.input-row>dd>*[type="checkbox"] {
|
||||
width: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.dm-loadout-container {
|
||||
max-height: 100%;
|
||||
max-width: 500px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dm-items-container {
|
||||
max-height: 100%;
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
.dm-items-container>div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
column-gap: 2px;
|
||||
}
|
||||
|
||||
.dm-items-container>div>label {
|
||||
width: 80px !important;
|
||||
}
|
||||
|
||||
.dm-items-container div>input:nth-of-type(1) {
|
||||
flex: 1;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.dm-items-container div>input:nth-of-type(2) {
|
||||
width: 40px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.dm-new-element-input {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
column-gap: 2px;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.dm-new-element-input>input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dm-new-element-input>button {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.dm-new-item-input {
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
}
|
||||
|
||||
.dm-new-item-input>button {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.tab-button {
|
||||
transform: translateY(+3px);
|
||||
background-color: var(--background-steel);
|
||||
border-radius: 0;
|
||||
border-bottom: 2px solid transparent !important;
|
||||
border-top: 2px solid #777777 !important;
|
||||
border-left: 2px solid #777777 !important;
|
||||
border-right: 0px solid #777777 !important;
|
||||
}
|
||||
|
||||
.tab-button.selected {
|
||||
background-color: var(--background-grey);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.tab-button:first-of-type {
|
||||
border-top-left-radius: 5px;
|
||||
}
|
||||
|
||||
.tab-button:last-of-type {
|
||||
border-top-right-radius: 5px;
|
||||
border-right: 2px solid #777777 !important;
|
||||
}
|
||||
|
||||
#database-manager-panel button :not(.dm-scroll-container>div) {
|
||||
border: 1px solid white;
|
||||
}
|
||||
103
frontend/website/plugins/databasemanager/tsconfig.json
Normal file
103
frontend/website/plugins/databasemanager/tsconfig.json
Normal file
@@ -0,0 +1,103 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||
/* Projects */
|
||||
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
/* Language and Environment */
|
||||
"target": "ES2017", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
||||
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||
/* Modules */
|
||||
"module": "commonjs", /* Specify what module code is generated. */
|
||||
"rootDirs": ["./src"], /* Specify the root folder within your source files. */
|
||||
// "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||
"typeRoots": [
|
||||
"./node_modules/@types",
|
||||
"../../@types"
|
||||
], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||
"types": [
|
||||
"olympus"
|
||||
], /* Specify type package names to be included without being referenced in a source file. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
||||
// "resolveJsonModule": true, /* Enable importing .json files. */
|
||||
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
||||
/* JavaScript Support */
|
||||
"allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
|
||||
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
||||
/* Emit */
|
||||
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
||||
// "outDir": "./", /* Specify an output folder for all emitted files. */
|
||||
// "removeComments": true, /* Disable emitting comments. */
|
||||
// "noEmit": true, /* Disable emitting files from a compilation. */
|
||||
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
|
||||
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
|
||||
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
|
||||
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
|
||||
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||
/* Interop Constraints */
|
||||
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
|
||||
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
|
||||
/* Type Checking */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
||||
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
||||
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
|
||||
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
||||
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
|
||||
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
||||
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
|
||||
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||
/* Completeness */
|
||||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
},
|
||||
"include": [
|
||||
"src/*.ts"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user