mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Merge branch 'manager-wizard' of https://github.com/Pax1601/DCSOlympus into manager-wizard
This commit is contained in:
commit
4a5c4ed7d7
25
client/@types/olympus/index.d.ts
vendored
25
client/@types/olympus/index.d.ts
vendored
@ -105,6 +105,10 @@ declare module "constants/constants" {
|
||||
export const ROEs: string[];
|
||||
export const reactionsToThreat: string[];
|
||||
export const emissionsCountermeasures: string[];
|
||||
export const ERAS: {
|
||||
name: string;
|
||||
chronologicalOrder: number;
|
||||
}[];
|
||||
export const ROEDescriptions: string[];
|
||||
export const reactionsToThreatDescriptions: string[];
|
||||
export const emissionsCountermeasuresDescriptions: string[];
|
||||
@ -836,6 +840,7 @@ declare module "other/utils" {
|
||||
}): UnitBlueprint | null;
|
||||
export function getMarkerCategoryByName(name: string): "aircraft" | "helicopter" | "groundunit-sam" | "navyunit" | "groundunit-other";
|
||||
export function getUnitDatabaseByCategory(category: string): import("unit/databases/aircraftdatabase").AircraftDatabase | import("unit/databases/helicopterdatabase").HelicopterDatabase | import("unit/databases/groundunitdatabase").GroundUnitDatabase | import("unit/databases/navyunitdatabase").NavyUnitDatabase | null;
|
||||
export function getCategoryBlueprintIconSVG(category: string, unitName: string): string | false;
|
||||
export function base64ToBytes(base64: string): ArrayBufferLike;
|
||||
export function enumToState(state: number): string;
|
||||
export function enumToROE(ROE: number): string;
|
||||
@ -1600,6 +1605,7 @@ declare module "map/map" {
|
||||
import { CoalitionAreaContextMenu } from "contextmenus/coalitionareacontextmenu";
|
||||
import { AirbaseSpawnContextMenu } from "contextmenus/airbasespawnmenu";
|
||||
export type MapMarkerVisibilityControl = {
|
||||
"category"?: string;
|
||||
"image": string;
|
||||
"isProtected"?: boolean;
|
||||
"name": string;
|
||||
@ -1997,6 +2003,25 @@ declare module "unit/importexport/unitdatafileexport" {
|
||||
showForm(units: Unit[]): void;
|
||||
}
|
||||
}
|
||||
declare module "schemas/schema" {
|
||||
import Ajv from "ajv";
|
||||
import { AnySchemaObject } from "ajv/dist/core";
|
||||
abstract class JSONSchemaValidator {
|
||||
#private;
|
||||
constructor(schema: AnySchemaObject);
|
||||
getAjv(): Ajv;
|
||||
getCompiledValidator(): any;
|
||||
getErrors(): any;
|
||||
getSchema(): AnySchemaObject;
|
||||
validate(data: any): any;
|
||||
}
|
||||
export class AirbasesJSONSchemaValidator extends JSONSchemaValidator {
|
||||
constructor();
|
||||
}
|
||||
export class ImportFileJSONSchemaValidator extends JSONSchemaValidator {
|
||||
constructor();
|
||||
}
|
||||
}
|
||||
declare module "unit/importexport/unitdatafileimport" {
|
||||
import { Dialog } from "dialog/dialog";
|
||||
import { UnitDataFile } from "unit/importexport/unitdatafile";
|
||||
|
||||
@ -60,6 +60,11 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.leaflet-container img.leaflet-tile {
|
||||
/* See: https://bugs.chromium.org/p/chromium/issues/detail?id=600120 */
|
||||
mix-blend-mode: plus-lighter;
|
||||
}
|
||||
|
||||
.leaflet-container.leaflet-touch-zoom {
|
||||
-ms-touch-action: pan-x pan-y;
|
||||
touch-action: pan-x pan-y;
|
||||
@ -646,7 +651,7 @@ svg.leaflet-image-layer.leaflet-interactive path {
|
||||
}
|
||||
|
||||
/* Printing */
|
||||
|
||||
|
||||
@media print {
|
||||
/* Prevent printers from removing background-images of controls. */
|
||||
.leaflet-control {
|
||||
|
||||
97
manager/1.js
Normal file
97
manager/1.js
Normal file
@ -0,0 +1,97 @@
|
||||
|
||||
/* Get the list of DCS instances */
|
||||
var instances = await DCSInstance.getInstances();
|
||||
|
||||
/* If there is only 1 DCS Instance and Olympus is not installed in it, go straight to the installation page (since there is nothing else to do) */
|
||||
this.basic = instances.length === 1 && !instances[0].installed;
|
||||
|
||||
document.getElementById("loader").classList.add("hide");
|
||||
|
||||
/* Check if there are corrupted or outdate instances */
|
||||
if (instances.some((instance) => {
|
||||
return instance.installed && instance.error;
|
||||
})) {
|
||||
/* Ask the user for confirmation */
|
||||
showErrorPopup("One or more Olympus instances are corrupted or need updating. Press Close to fix this.", async () => {
|
||||
showWaitPopup("Please wait while your instances are being fixed.")
|
||||
fixInstances(instances.filter((instance) => {
|
||||
return instance.installed && instance.error;
|
||||
})).then(
|
||||
() => { location.reload() },
|
||||
(err) => {
|
||||
logger.error(err);
|
||||
showErrorPopup(`An error occurred while trying to fix your installations. Please reinstall Olympus manually. <br><br> You can find more info in ${path.join(__dirname, "..", "manager.log")}`);
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/* Check which buttons should be enabled */
|
||||
const installEnabled = true;
|
||||
const manageEnabled = instances.some((instance) => { return instance.installed; });
|
||||
|
||||
/* Menu */
|
||||
var menuPage = new MenuPage(this, {
|
||||
installEnabled: installEnabled,
|
||||
manageEnabled: manageEnabled
|
||||
});
|
||||
|
||||
/* Installations */
|
||||
this.installationPage = new installationPage(this, {
|
||||
instances: instances
|
||||
});
|
||||
|
||||
/* Instances */
|
||||
this.instancesPage = new InstancesPage(this, {
|
||||
instances: instances.filter((instance) => {
|
||||
return instance.installed;
|
||||
})
|
||||
});
|
||||
|
||||
/* Connections */
|
||||
this.connectionsPage = new ConnectionsPage(this);
|
||||
|
||||
/* Passwords */
|
||||
this.passwordsPage = new PasswordsPage(this);
|
||||
|
||||
/* Result */
|
||||
this.resultPage = new ResultPage(this, {
|
||||
logLocation: path.join(__dirname, "..", "manager.log")
|
||||
});
|
||||
|
||||
/* Create all the HTML pages */
|
||||
document.body.appendChild(this.menuPage.getElement());
|
||||
document.body.appendChild(this.installationPage.getElement());
|
||||
document.body.appendChild(this.instancesPage.getElement());
|
||||
document.body.appendChild(this.connectionsPage.getElement());
|
||||
document.body.appendChild(this.passwordsPage.getElement());
|
||||
document.body.appendChild(this.resultPage.getElement());
|
||||
|
||||
/* In basic mode we directly show the connections page */
|
||||
if (this.basic) {
|
||||
const options = {
|
||||
instance: instances[0],
|
||||
basic: this.basic,
|
||||
install: true
|
||||
}
|
||||
connectionsPage.options = {
|
||||
...connectionsPage.options,
|
||||
...options
|
||||
}
|
||||
passwordsPage.options = {
|
||||
...passwordsPage.options,
|
||||
...options
|
||||
}
|
||||
resultPage.options = {
|
||||
...resultPage.options,
|
||||
...options
|
||||
}
|
||||
|
||||
/* Show the connections page directly */
|
||||
instancesPage.hide();
|
||||
connectionsPage.show();
|
||||
} else {
|
||||
/* Show the main menu */
|
||||
menuPage.show();
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,33 @@
|
||||
<style>
|
||||
#manager-connections .option {
|
||||
background-color: var(--background);
|
||||
border: 1px solid var(--offwhite);
|
||||
width: 220px;
|
||||
height: 60px;
|
||||
color: var(--offwhite);
|
||||
display: flex;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
padding-left: 15px;
|
||||
align-items: center;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
color: var(--offwhite);
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#manager-connections .option:hover {
|
||||
color: var(--background);
|
||||
background-color: var(--offwhite);
|
||||
}
|
||||
|
||||
#manager-connections .buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 15px;
|
||||
}
|
||||
|
||||
#manager-connections .success,
|
||||
#manager-connections .error {
|
||||
position: absolute;
|
||||
@ -29,65 +58,85 @@
|
||||
</style>
|
||||
<div id="manager-connections">
|
||||
<div class="step-summary">
|
||||
<div class="blue <%= !install || simplified? 'hide': '' %>">User path</div>
|
||||
<div class="blue <%= singleInstance? 'hide': '' %>"><%= install? 'User path': 'Instance selection' %></div>
|
||||
<div class="blue">Type of install</div>
|
||||
<div class="white">Ports and address</div>
|
||||
<div class="empty">Passwords</div>
|
||||
<div class="empty"> <%= install? 'Install': 'Update' %></div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="instructions">
|
||||
<span>
|
||||
Accept or modify port settings (optional)
|
||||
</span>
|
||||
<span>
|
||||
If you are installing Olympus locally for Single player use, it's recommended you leave these as default and continue.
|
||||
If you are installing a dedicated server, then follow the instructions available on the DCS Olympus Wiki.
|
||||
</span>
|
||||
</div>
|
||||
<div class="input-group client-port">
|
||||
<span>Client port
|
||||
<img src="./icons/circle-info-solid.svg" title="This port is used to allow access to Olympus. Be sure to allow this port through your firewall if you want people to connect remotely">
|
||||
</span>
|
||||
<div>
|
||||
<input type="number" min="1024" max="65535" value="<%= instance["clientPort"] %>">
|
||||
<img class="success hide">
|
||||
<div class="error hide">
|
||||
<img> <span>Port already in use</span>
|
||||
<% if (selectAutoOrManual) { %>
|
||||
<div class="instructions">
|
||||
<span>
|
||||
Do you want to set port and address settings manually?
|
||||
</span>
|
||||
<span>
|
||||
We can auto setup ports and addresses for you, or you can set the manually. <br>
|
||||
If you don't have an understanding of how Olympus works, we recommend the auto option.
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="buttons">
|
||||
<div class="option button auto">
|
||||
Auto apply settings
|
||||
</div>
|
||||
<div class="option button manual">
|
||||
Manually set options
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group backend-port">
|
||||
<span>Backend port
|
||||
<img src="./icons/circle-info-solid.svg" title="This port is used to allow access to Olympus. Be sure to allow this port through your firewall if you want people to connect remotely.">
|
||||
</span>
|
||||
<div>
|
||||
<input type="number" min="1024" max="65535" value="<%= instance["backendPort"] %>">
|
||||
<img class="success hide">
|
||||
<div class="error hide">
|
||||
<img> <span>Port already in use</span>
|
||||
|
||||
<% } else { %>
|
||||
<div class="instructions">
|
||||
<span>
|
||||
Enter the ports and address to use.
|
||||
</span>
|
||||
<span>
|
||||
Select client and backend ports, making sure they are free to use with the provided check. <br>
|
||||
Unless you want to support direct API calls to the backend, you can keep the address to localhost even for dedicated servers.
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="input-group client-port">
|
||||
<span>Client port
|
||||
<img src="./icons/circle-info-solid.svg" title="This port is used to allow access to Olympus. Be sure to allow this port through your firewall if you want people to connect remotely">
|
||||
</span>
|
||||
<div>
|
||||
<input type="number" min="1024" max="65535" value="<%= activeInstance["clientPort"] %>">
|
||||
<img class="success hide">
|
||||
<div class="error hide">
|
||||
<img> <span>Port already in use</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group backend-address">
|
||||
<span>Backend address
|
||||
<img src="./icons/circle-info-solid.svg" title="This is the backend address Olympus will listen on. Unless you know what you are doing, leave it as localhost, even for dedicated server installations.">
|
||||
</span>
|
||||
<input type="text" value="<%= instance["backendAddress"] %>">
|
||||
</div>
|
||||
<div class="input-group backend-port">
|
||||
<span>Backend port
|
||||
<img src="./icons/circle-info-solid.svg" title="This port is used to allow access to Olympus. Be sure to allow this port through your firewall if you want people to connect remotely.">
|
||||
</span>
|
||||
<div>
|
||||
<input type="number" min="1024" max="65535" value="<%= activeInstance["backendPort"] %>">
|
||||
<img class="success hide">
|
||||
<div class="error hide">
|
||||
<img> <span>Port already in use</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group backend-address">
|
||||
<span>Backend address
|
||||
<img src="./icons/circle-info-solid.svg" title="This is the backend address Olympus will listen on. Unless you know what you are doing, leave it as localhost, even for dedicated server installations.">
|
||||
</span>
|
||||
<input type="text" value="<%= activeInstance["backendAddress"] %>">
|
||||
</div>
|
||||
<% } %>
|
||||
<div class="buttons-footer">
|
||||
<% if (!simplified) { %>
|
||||
<div class="button back">
|
||||
Back
|
||||
</div>
|
||||
<% } %>
|
||||
<div class="button next">
|
||||
Next
|
||||
</div>
|
||||
</div>
|
||||
<% if (!simplified) { %>
|
||||
<div class="button cancel">
|
||||
<%= install? "Cancel installation": "Cancel editing" %>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
@ -88,27 +88,41 @@
|
||||
</style>
|
||||
<div id="manager-installations">
|
||||
<div class="step-summary">
|
||||
<div class="white">User path</div>
|
||||
<div class="white <%= singleInstance? 'hide': '' %>"><%= install? 'User path': 'Instance selection' %></div>
|
||||
<div class="blue">Type of install</div>
|
||||
<div class="empty">Ports and address</div>
|
||||
<div class="empty">Passwords</div>
|
||||
<div class="empty">Install</div>
|
||||
<div class="empty"> <%= install? 'Install': 'Update' %></div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="instructions">
|
||||
<span>
|
||||
Select a DCS path to install Olympus to.
|
||||
<% if (install) { %>
|
||||
Select a DCS path to install Olympus to.
|
||||
<% } else { %>
|
||||
Select an Olympus instance to edit.
|
||||
<% } %>
|
||||
</span>
|
||||
<span>
|
||||
We have automatically detected the following DCS installations under your Saved Games / DCS folder.
|
||||
<% if (install) { %>
|
||||
We have automatically detected the following DCS installations under your Saved Games / DCS folder.
|
||||
<% } else { %>
|
||||
These are the DCS instances in which Olympus has already been installed.
|
||||
<% } %>
|
||||
</span>
|
||||
<span>
|
||||
Please select which DCS installations you want to add Olympus to.
|
||||
<% if (install) { %>
|
||||
Please select which DCS installations you want to add Olympus to.
|
||||
<% } else { %>
|
||||
Please select which Olympus installations you want to edit.
|
||||
<% } %>
|
||||
|
||||
</span>
|
||||
</div>
|
||||
<div class="scroll-container">
|
||||
<div class="scrollable">
|
||||
<% for (let i = 0; i < instances.length; i++) {%>
|
||||
<div class="option <%= instances[i].installed? 'installed': '' %>" data-folder="<%= instances[i].folder %>">
|
||||
<div class="option" data-folder="<%= instances[i].folder %>">
|
||||
<span><%= instances[i].name %></span>
|
||||
<span><img src="./icons/folder-open-solid.svg"> <%= instances[i].folder %></span>
|
||||
<span class="<%= instances[i].installed? (instances[i].error? 'error': 'installed'): '' %>">
|
||||
@ -118,9 +132,12 @@
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="button cancel">
|
||||
Cancel installation
|
||||
<% if (install) { %>
|
||||
Cancel installation
|
||||
<% } else { %>
|
||||
Cancel editing
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -36,6 +36,18 @@
|
||||
row-gap: 25px;
|
||||
}
|
||||
|
||||
#manager-instances .option:not(.installed) {
|
||||
background-color: var(--background-disabled);
|
||||
}
|
||||
|
||||
#manager-instances .option:not(.installed) .info {
|
||||
opacity: 50%;
|
||||
}
|
||||
|
||||
#manager-instances .option:not(.installed) .server-data {
|
||||
opacity: 50%;
|
||||
}
|
||||
|
||||
#manager-instances>.instructions {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@ -192,6 +204,7 @@
|
||||
}
|
||||
|
||||
#manager-instances .edit,
|
||||
#manager-instances .install,
|
||||
#manager-instances .uninstall,
|
||||
#manager-instances .stop {
|
||||
color: var(--offwhite);
|
||||
@ -200,34 +213,36 @@
|
||||
}
|
||||
|
||||
#manager-instances .edit:hover,
|
||||
#manager-instances .install:hover,
|
||||
#manager-instances .uninstall:hover,
|
||||
#manager-instances .stop:hover {
|
||||
color: var(--background);
|
||||
background-color: var(--offwhite);
|
||||
}
|
||||
|
||||
#manager-instances .install {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
<div id="manager-instances">
|
||||
<div class="content">
|
||||
<div class="button cancel">
|
||||
<img src="./icons/chevron-left-solid.svg"/> Return to menu
|
||||
</div>
|
||||
<div class="instructions">
|
||||
<span>
|
||||
View and manage installs
|
||||
</span>
|
||||
<span>
|
||||
The following Oympus installs have been identified. <br>You can start an Olympus server, modify settings and uninstall below.
|
||||
The following DCS installations have been identified. <br>You can start an Olympus server, modify settings and uninstall below.
|
||||
</span>
|
||||
</div>
|
||||
<div class="scroll-container">
|
||||
<div class="scrollable">
|
||||
<% for (let i = 0; i < instances.length; i++) {%>
|
||||
<div class="option" data-folder="<%= instances[i].folder %>">
|
||||
<div class="option <%= instances[i].installed? 'installed': '' %>" data-folder="<%= instances[i].folder %>">
|
||||
<div class="instance-info">
|
||||
<span><%= instances[i].name %></span>
|
||||
<span class="<%= instances[i].installed? (instances[i].error? 'error': ''): '' %>">
|
||||
<%= instances[i].installed? (instances[i].error? 'Corrupted/outdated Olympus installation': ''): '' %>
|
||||
<span class="<%= instances[i].installed? (instances[i].error? 'error': 'installed'): '' %>">
|
||||
<%= instances[i].installed? (instances[i].error? 'Corrupted/outdated Olympus installation': 'Olympus installed'): 'Olympus not installed' %>
|
||||
</span>
|
||||
<span><img src="./icons/folder-open-solid.svg"> <%= instances[i].folder %></span>
|
||||
<div class="server-data">
|
||||
@ -242,15 +257,15 @@
|
||||
<div class="divider"></div>
|
||||
<div class="info">
|
||||
<div>Client port</div>
|
||||
<div> <%= instances[i].clientPort %> </div>
|
||||
<div> <%= instances[i].installed? instances[i].clientPort: "N/A" %> </div>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div>Backend port</div>
|
||||
<div> <%= instances[i].backendPort %> </div>
|
||||
<div> <%= instances[i].installed? instances[i].backendPort: "N/A" %> </div>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div>Backend address</div>
|
||||
<div> <%= instances[i].backendAddress %> </div>
|
||||
<div> <%= instances[i].installed? instances[i].backendAddress: "N/A" %> </div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="instance-buttons">
|
||||
@ -263,6 +278,7 @@
|
||||
</div>
|
||||
|
||||
<div class="button edit">Edit settings</div>
|
||||
<div class="button install">Install Olympus</div>
|
||||
<div class="button uninstall">Uninstall Olympus</div>
|
||||
<div class="button open-browser hide">Open in browser</div>
|
||||
<div class="button stop hide">Stop Olympus</div>
|
||||
|
||||
@ -1,62 +1,55 @@
|
||||
<style>
|
||||
#summary {
|
||||
width: 70%;
|
||||
#manager-menu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-direction: row;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
color: var(--offwhite);
|
||||
padding: 80px;
|
||||
min-height: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#summary .icon {
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
margin-bottom: -30px;
|
||||
}
|
||||
|
||||
#summary div:nth-child(1) {
|
||||
font-size: 50px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#summary div:nth-child(2) {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#summary div:nth-child(3) {
|
||||
color: var(--lightgray);
|
||||
font-size: 13px;
|
||||
font-weight: normal;
|
||||
margin-top: 20px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
#manager-menu #menu {
|
||||
#manager-menu>div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 20px;
|
||||
width: 60%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#manager-menu .option {
|
||||
background-color: var(--background);
|
||||
border: 1px solid var(--offwhite);
|
||||
width: 460px;
|
||||
height: 70px;
|
||||
height: 110px;
|
||||
color: var(--offwhite);
|
||||
display: flex;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
padding-left: 15px;
|
||||
align-items: center;
|
||||
align-items: start;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
color: var(--offwhite);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
row-gap: 15px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#manager-menu .option>div {
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#manager-menu .option::after {
|
||||
position: absolute;
|
||||
display: block;
|
||||
content: " ";
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image: url("./icons/chevron-right-solid.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: 50% 50%;
|
||||
right: 15px;
|
||||
}
|
||||
|
||||
#manager-menu .option:hover {
|
||||
@ -73,20 +66,31 @@
|
||||
#manager-menu .option * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
<div id="manager-menu">
|
||||
<div id="summary">
|
||||
<div>DCS OLYMPUS <img class="icon" src="../img/OlympusLogoFinal_4k.png" \></div>
|
||||
<div>INSTALL WIZARD AND MANAGER</div>
|
||||
<div>Using this manager, you can install Olympus, update settings, and view and manage instances</div>
|
||||
</div>
|
||||
<div id="menu">
|
||||
<div class="option install <%= installEnabled? '': 'disabled' %>">
|
||||
Install Olympus
|
||||
<div id="summary" style="width: 70%; height: 100%; color: var(--offwhite); padding: 80px;">
|
||||
<div style="font-size: 50px; font-weight: bold;">
|
||||
DCS OLYMPUS <img src="../img/OlympusLogoFinal_4k.png" style="height: 100px; width: 100px; margin-bottom: -30px;"\>
|
||||
</div>
|
||||
<div class="option manage <%= manageEnabled? '': 'disabled' %>">
|
||||
View / Manage installs
|
||||
<div style="font-size: 20px; font-weight: bold;">
|
||||
INSTALL WIZARD AND MANAGER
|
||||
</div>
|
||||
<div style="color: var(--lightgray); font-size: 13px; font-weight: normal; margin-top: 20px; width: 300px;">
|
||||
Using this manager, you can install Olympus, update settings, and view and manage instances
|
||||
</div>
|
||||
</div>
|
||||
<div id="menu" style="row-gap: 20px; width: 60%;">
|
||||
<div class="option <%= installEnabled? '': 'disabled' %>" onclick="signal('onInstallClicked')">
|
||||
Add Olympus
|
||||
<div>
|
||||
Add or update Olympus to a new DCS instance
|
||||
</div>
|
||||
</div>
|
||||
<div class="option <%= editEnabled? '': 'disabled' %>" onclick="signal('onEditClicked')">
|
||||
Change settings
|
||||
<div>
|
||||
Adjust port, address and password settings
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -3,7 +3,8 @@
|
||||
</style>
|
||||
<div id="manager-passwords">
|
||||
<div class="step-summary">
|
||||
<div class="blue <%= !install || simplified? 'hide': '' %>">User path</div>
|
||||
<div class="blue <%= singleInstance? 'hide': '' %>"><%= install? 'User path': 'Instance selection' %></div>
|
||||
<div class="blue">Type of install</div>
|
||||
<div class="blue">Ports and address</div>
|
||||
<div class="white">Passwords</div>
|
||||
<div class="empty"> <%= install? 'Install': 'Update' %></div>
|
||||
@ -41,7 +42,7 @@
|
||||
Next
|
||||
</div>
|
||||
</div>
|
||||
<% if (!simplified) { %>
|
||||
<% if (!singleInstance) { %>
|
||||
<div class="button cancel">
|
||||
<%= install? "Cancel installation": "Cancel editing" %>
|
||||
</div>
|
||||
|
||||
@ -129,10 +129,10 @@
|
||||
<img class="wait"><img class="success hide"><img class="error hide">
|
||||
<div>
|
||||
<span>
|
||||
<%= instance.name %>
|
||||
<%= activeInstance.name %>
|
||||
</span>
|
||||
<span><img src="./icons/folder-open-solid.svg">
|
||||
<%= instance.folder %>
|
||||
<%= activeInstance.folder %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
23
manager/ejs/type.ejs
Normal file
23
manager/ejs/type.ejs
Normal file
@ -0,0 +1,23 @@
|
||||
<style>
|
||||
|
||||
</style>
|
||||
<div class="instructions">
|
||||
<div class="step">
|
||||
Step 1 of 4
|
||||
</div>
|
||||
<div class="title">
|
||||
Do you want to add Olympus for singleplayer or multiplayer?
|
||||
</div>
|
||||
<div class="description">
|
||||
Select singleplayer if you only want to play locally on your own computer. <br>
|
||||
Select multiplayer if you want Olympus to be useable over the internet from a different computer, or this instance is a dedicated server.
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<div class="button">
|
||||
Singleplayer
|
||||
</div>
|
||||
<div class="button">
|
||||
Multiplayer
|
||||
</div>
|
||||
</div>
|
||||
67
manager/ejs/welcome.ejs
Normal file
67
manager/ejs/welcome.ejs
Normal file
@ -0,0 +1,67 @@
|
||||
<style>
|
||||
#manager-welcome {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 20px;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#manager-welcome .instructions {
|
||||
width: 40%;
|
||||
text-align: center;
|
||||
color: var(--offwhite);
|
||||
}
|
||||
|
||||
#manager-welcome .option {
|
||||
background-color: var(--background);
|
||||
border: 1px solid var(--offwhite);
|
||||
width: 460px;
|
||||
height: 70px;
|
||||
color: var(--offwhite);
|
||||
display: flex;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
padding-left: 15px;
|
||||
align-items: center;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
color: var(--offwhite);
|
||||
}
|
||||
|
||||
#manager-welcome .option:hover {
|
||||
color: var(--background);
|
||||
background-color: var(--offwhite);
|
||||
}
|
||||
|
||||
#manager-welcome .option.disabled {
|
||||
pointer-events: none;
|
||||
color: var(--darkgray);
|
||||
border-color: var(--darkgray);
|
||||
}
|
||||
|
||||
#manager-welcome .option * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
<div id="manager-welcome">
|
||||
<div class="instructions" style="font-size: 28px; font-weight: bold;">
|
||||
Do you want to use the Olympus Manager in basic or Expert mode?
|
||||
</div>
|
||||
<div class="instructions" style="color: var(--gray);">
|
||||
Basic mode is recommended for most users. <br>
|
||||
Expert mode is for those who know how Olympus works or for server owners.
|
||||
</div>
|
||||
<div class="instructions" style="color: var(--gray); font-weight: bold;">
|
||||
You can change this setting at any time.
|
||||
</div>
|
||||
<div class="option basic" onclick="signal('onBasicClicked')">
|
||||
Basic mode
|
||||
</div>
|
||||
<div class="option expert" onclick="signal('onExpertClicked')">
|
||||
Expert mode
|
||||
</div>
|
||||
</div>
|
||||
53
manager/ejs/wizard.ejs
Normal file
53
manager/ejs/wizard.ejs
Normal file
@ -0,0 +1,53 @@
|
||||
<style>
|
||||
.wizard-page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 30px;
|
||||
padding: 60px 120px;
|
||||
}
|
||||
|
||||
.buttons-footer {
|
||||
display: flex;
|
||||
column-gap: 10px;
|
||||
justify-content: start;
|
||||
}
|
||||
|
||||
.instructions {
|
||||
color: var(--offwhite);
|
||||
}
|
||||
|
||||
.instructions .step {
|
||||
|
||||
}
|
||||
|
||||
.instructions .title {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.content {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 20px;
|
||||
align-items: start;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
<div class="wizard-page">
|
||||
<div class="cancel" style="font-size: 14px; font-weight: 600; color: var(--offwhite); display: flex; align-items: center; column-gap: 10px;">
|
||||
<img src="./icons/chevron-left-solid.svg" style="height: 14px;">Cancel install
|
||||
</div>
|
||||
<div class="content">
|
||||
|
||||
</div>
|
||||
<div class="buttons-footer">
|
||||
<div class="button back" style="color: var(--offwhite); background-color: var(--background); border: 1px solid var(--offwhite);">
|
||||
Back
|
||||
</div>
|
||||
<div class="button next" style="color: var(--background); background-color: var(--offwhite);">
|
||||
Next
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -20,18 +20,20 @@
|
||||
<button class="title-bar-button maximize"></button>
|
||||
<button class="title-bar-button close"></button>
|
||||
</div>
|
||||
<div id="header">
|
||||
<div id="header" class="hide">
|
||||
<img class="main-icon" src="../img/OlympusLogoFinal_4k.png" \>
|
||||
<div class="version">
|
||||
<div> DCS Olympus Manager</div>
|
||||
<div class="accent-green">{{OLYMPUS_VERSION_NUMBER}}</div>
|
||||
</div>
|
||||
<div class="link first" data-link="https://github.com/Pax1601/DCSOlympus/wiki/2.-User-Guide">User Guide</div>
|
||||
<div class="link" data-link="https://github.com/Pax1601/DCSOlympus/wiki/Setup-Troubleshooting">Troubleshooting Guide</div>
|
||||
<div class="link" data-link="https://github.com/Pax1601/DCSOlympus/wiki/Setup-Troubleshooting">Troubleshooting
|
||||
Guide</div>
|
||||
<div id="switch-mode" class="link"> </div>
|
||||
<div style="width: 15px;"></div>
|
||||
<img class="link" data-link="https://github.com/Pax1601/DCSOlympus" src="./icons/github.svg"/>
|
||||
<img class="link" data-link="https://discord.gg/pCfCykAdrw" src="./icons/discord.svg"/>
|
||||
<img class="link" data-link="https://www.youtube.com/@DCSOlympus" src="./icons/youtube.svg"/>
|
||||
<img class="link" data-link="https://github.com/Pax1601/DCSOlympus" src="./icons/github.svg" />
|
||||
<img class="link" data-link="https://discord.gg/pCfCykAdrw" src="./icons/discord.svg" />
|
||||
<img class="link" data-link="https://www.youtube.com/@DCSOlympus" src="./icons/youtube.svg" />
|
||||
</div>
|
||||
<div id="loader" class="manager-page hide">
|
||||
Loading, please wait...
|
||||
@ -42,7 +44,7 @@
|
||||
<img src="./icons/circle-question-regular.svg" class="confirm">
|
||||
<img src="./icons/spinner-solid.svg" class="wait">
|
||||
<div class="content">
|
||||
|
||||
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="button accept-popup"> Accept </div>
|
||||
@ -77,6 +79,11 @@
|
||||
document.querySelector('.restore').classList.add("hide");
|
||||
document.querySelector('.maximize').classList.remove("hide");
|
||||
})
|
||||
|
||||
function signal(callback, params) {
|
||||
const event = new CustomEvent("signal", { detail: { callback: callback, params: params } });
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
</script>
|
||||
|
||||
</html>
|
||||
@ -6,58 +6,73 @@ const { logger } = require("./filesystem")
|
||||
*
|
||||
*/
|
||||
class ConnectionsPage extends ManagerPage {
|
||||
onBackClicked;
|
||||
onNextClicked;
|
||||
onCancelClicked;
|
||||
instance;
|
||||
|
||||
constructor(options) {
|
||||
super(options);
|
||||
constructor(manager, options) {
|
||||
super(manager, options);
|
||||
}
|
||||
|
||||
render(str) {
|
||||
const element = this.getElement();
|
||||
element.innerHTML = str;
|
||||
|
||||
if (this.element.querySelector(".back"))
|
||||
this.element.querySelector(".back").addEventListener("click", (e) => this.onBackClicked(e));
|
||||
if (this.element.querySelector(".button.auto"))
|
||||
this.element.querySelector(".button.auto").addEventListener("click", (e) => this.onOptionSelected(true));
|
||||
|
||||
if (this.element.querySelector(".next"))
|
||||
this.element.querySelector(".next").addEventListener("click", (e) => this.onNextClicked(e));
|
||||
if (this.element.querySelector(".button.manual"))
|
||||
this.element.querySelector(".button.manual").addEventListener("click", (e) => this.onOptionSelected(false));
|
||||
|
||||
if (this.element.querySelector(".cancel"))
|
||||
this.element.querySelector(".cancel").addEventListener("click", (e) => this.onCancelClicked(e));
|
||||
if (this.element.querySelector(".client-port"))
|
||||
this.element.querySelector(".client-port").querySelector("input").addEventListener("change", async (e) => { this.setClientPort(Number(e.target.value)); })
|
||||
|
||||
this.element.querySelector(".client-port").querySelector("input").addEventListener("change", async (e) => { this.setClientPort(Number(e.target.value)); })
|
||||
this.element.querySelector(".backend-port").querySelector("input").addEventListener("change", async (e) => { this.setBackendPort(Number(e.target.value)); })
|
||||
this.element.querySelector(".backend-address").querySelector("input").addEventListener("change", async (e) => { this.instance.setBackendAddress(e.target.value); })
|
||||
if (this.element.querySelector(".backend-port"))
|
||||
this.element.querySelector(".backend-port").querySelector("input").addEventListener("change", async (e) => { this.setBackendPort(Number(e.target.value)); })
|
||||
|
||||
if (this.element.querySelector(".backend-address"))
|
||||
this.element.querySelector(".backend-address").querySelector("input").addEventListener("change", async (e) => { this.manager.getActiveInstance().setBackendAddress(e.target.value); })
|
||||
|
||||
super.render();
|
||||
}
|
||||
|
||||
show() {
|
||||
this.instance = this.options.instance;
|
||||
|
||||
ejs.renderFile("./ejs/connections.ejs", this.options, {}, (err, str) => {
|
||||
show(previousPage) {
|
||||
ejs.renderFile("./ejs/connections.ejs", {...this.options, ...this.manager.options}, {}, (err, str) => {
|
||||
if (!err) {
|
||||
this.render(str);
|
||||
|
||||
/* Call the port setters to check if the ports are free */
|
||||
this.setClientPort(this.instance.clientPort);
|
||||
this.setBackendPort(this.instance.backendPort);
|
||||
this.setClientPort(this.manager.getActiveInstance().clientPort);
|
||||
this.setBackendPort(this.manager.getActiveInstance().backendPort);
|
||||
} else {
|
||||
logger.error(err);
|
||||
}
|
||||
});
|
||||
|
||||
super.show();
|
||||
super.show(previousPage);
|
||||
}
|
||||
|
||||
onNextClicked() {
|
||||
this.hide();
|
||||
this.manager.passwordsPage.show(this);
|
||||
}
|
||||
|
||||
onCancelClicked() {
|
||||
this.hide();
|
||||
this.manager.menuPage.show()
|
||||
}
|
||||
|
||||
onOptionSelected(auto) {
|
||||
this.options.selectAutoOrManual = false;
|
||||
this.options.auto = auto;
|
||||
if (auto) {
|
||||
|
||||
} else {
|
||||
this.show();
|
||||
}
|
||||
}
|
||||
|
||||
/** Asynchronously check if the client port is free and if it is, set the new value
|
||||
*
|
||||
*/
|
||||
async setClientPort(newPort) {
|
||||
const success = await this.instance.setClientPort(newPort);
|
||||
const success = await this.manager.getActiveInstance().setClientPort(newPort);
|
||||
var successEls = this.element.querySelector(".client-port").querySelectorAll(".success");
|
||||
for (let i = 0; i < successEls.length; i++) {
|
||||
successEls[i].classList.toggle("hide", !success);
|
||||
@ -72,7 +87,7 @@ class ConnectionsPage extends ManagerPage {
|
||||
*
|
||||
*/
|
||||
async setBackendPort(newPort) {
|
||||
const success = await this.instance.setBackendPort(newPort);
|
||||
const success = await this.manager.getActiveInstance().setBackendPort(newPort);
|
||||
var successEls = this.element.querySelector(".backend-port").querySelectorAll(".success");
|
||||
for (let i = 0; i < successEls.length; i++) {
|
||||
successEls[i].classList.toggle("hide", !success);
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
const { getManager } = require('./managerfactory')
|
||||
var regedit = require('regedit')
|
||||
const shellFoldersKey = 'HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders'
|
||||
const saveGamesKey = '{4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4}'
|
||||
@ -124,33 +125,7 @@ class DCSInstance {
|
||||
/* Periodically "ping" Olympus to check if either the client or the backend are active */
|
||||
window.setInterval(async () => {
|
||||
await this.getData();
|
||||
|
||||
var page = document.getElementById("manager-instances");
|
||||
if (page) {
|
||||
var instanceDivs = page.querySelectorAll(`.option`);
|
||||
for (let i = 0; i < instanceDivs.length; i++) {
|
||||
if (instanceDivs[i].dataset.folder == this.folder) {
|
||||
var instanceDiv = instanceDivs[i];
|
||||
if (instanceDiv.querySelector(".webserver.online") !== null) {
|
||||
instanceDiv.querySelector(".webserver.online").classList.toggle("hide", !this.webserverOnline)
|
||||
instanceDiv.querySelector(".webserver.offline").classList.toggle("hide", this.webserverOnline)
|
||||
instanceDiv.querySelector(".backend.online").classList.toggle("hide", !this.backendOnline)
|
||||
instanceDiv.querySelector(".backend.offline").classList.toggle("hide", this.backendOnline)
|
||||
|
||||
if (this.backendOnline) {
|
||||
instanceDiv.querySelector(".fps .data").innerText = this.fps;
|
||||
instanceDiv.querySelector(".load .data").innerText = this.load;
|
||||
}
|
||||
|
||||
instanceDiv.querySelector(".button.start").classList.toggle("hide", this.webserverOnline)
|
||||
instanceDiv.querySelector(".button.uninstall").classList.toggle("hide", this.webserverOnline)
|
||||
instanceDiv.querySelector(".button.edit").classList.toggle("hide", this.webserverOnline)
|
||||
instanceDiv.querySelector(".button.open-browser").classList.toggle("hide", !this.webserverOnline)
|
||||
instanceDiv.querySelector(".button.stop").classList.toggle("hide", !this.webserverOnline)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
getManager().instancesPage.update();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
@ -367,7 +342,7 @@ class DCSInstance {
|
||||
|
||||
/* Uninstall this instance */
|
||||
uninstall() {
|
||||
showConfirmPopup("Are you sure you want to completely remove this Olympus installation?", () =>
|
||||
showConfirmPopup("<div style='font-size: 18px; max-width: 100%'> Are you sure you want to remove Olympus? </div> If you click Accept, the Olympus mod will be removed from your DCS installation.", () =>
|
||||
uninstallInstance(this.folder, this.name).then(
|
||||
() => {
|
||||
location.reload();
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
const DCSInstance = require("./dcsinstance");
|
||||
const ManagerPage = require("./managerpage");
|
||||
const ejs = require('ejs')
|
||||
const { logger } = require("./filesystem")
|
||||
const { logger } = require("./filesystem");
|
||||
const { showConfirmPopup } = require("./popup");
|
||||
|
||||
class InstallationsPage extends ManagerPage {
|
||||
onCancelClicked;
|
||||
setSelectedInstance;
|
||||
|
||||
constructor(options) {
|
||||
super(options);
|
||||
class installationPage extends ManagerPage {
|
||||
constructor(manager, options) {
|
||||
super(manager, options);
|
||||
}
|
||||
|
||||
render(str) {
|
||||
@ -19,17 +17,18 @@ class InstallationsPage extends ManagerPage {
|
||||
options[i].onclick = (e) => {this.onOptionClicked(e);}
|
||||
}
|
||||
|
||||
this.element.querySelector(".cancel").addEventListener("click", (e) => this.onCancelClicked(e));
|
||||
if (this.element.querySelector(".cancel"))
|
||||
this.element.querySelector(".cancel").addEventListener("click", (e) => this.onCancelClicked(e));
|
||||
|
||||
super.render();
|
||||
}
|
||||
|
||||
async onOptionClicked(e) {
|
||||
this.setSelectedInstance((await DCSInstance.getInstances()).find((instance) => {return instance.folder === e.target.dataset.folder}));
|
||||
this.onInstanceSelection((await DCSInstance.getInstances()).find((instance) => {return instance.folder === e.target.dataset.folder}));
|
||||
}
|
||||
|
||||
show() {
|
||||
ejs.renderFile("./ejs/installations.ejs", this.options, {}, (err, str) => {
|
||||
show(previousPage) {
|
||||
ejs.renderFile("./ejs/installations.ejs", {...this.options, ...this.manager.options}, {}, (err, str) => {
|
||||
if (!err) {
|
||||
this.render(str);
|
||||
} else {
|
||||
@ -37,8 +36,32 @@ class InstallationsPage extends ManagerPage {
|
||||
}
|
||||
});
|
||||
|
||||
super.show();
|
||||
super.show(previousPage);
|
||||
}
|
||||
|
||||
onInstanceSelection(activeInstance) {
|
||||
this.manager.options.activeInstance = activeInstance;
|
||||
this.manager.options.install = !activeInstance.installed;
|
||||
|
||||
/* Show the connections page */
|
||||
if (!activeInstance.installed || !this.managers.options.install) {
|
||||
this.hide();
|
||||
this.manager.typePage.show(this);
|
||||
} else {
|
||||
showConfirmPopup("<div style='font-size: 18px; max-width: 100%'> Olympus is already installed in this instance! </div> If you click Accept, it will be installed again and all changes, e.g. custom databases or mods support, will be lost. Are you sure you want to continue?",
|
||||
() => {
|
||||
this.hide();
|
||||
this.manager.typePage.show(this);
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
onCancelClicked(e) {
|
||||
/* Go back to the main menu */
|
||||
this.hide();
|
||||
this.manager.menuPage.show();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = InstallationsPage;
|
||||
module.exports = installationPage;
|
||||
@ -6,12 +6,10 @@ const { exec } = require("child_process");
|
||||
const { logger } = require("./filesystem")
|
||||
|
||||
class InstancesPage extends ManagerPage {
|
||||
onCancelClicked;
|
||||
setSelectedInstance;
|
||||
startInstance;
|
||||
|
||||
constructor(options) {
|
||||
super(options);
|
||||
constructor(manager, options) {
|
||||
super(manager, options);
|
||||
}
|
||||
|
||||
render(str) {
|
||||
@ -22,6 +20,11 @@ class InstancesPage extends ManagerPage {
|
||||
editButtons[i].onclick = (e) => {this.onEditClicked(e);}
|
||||
}
|
||||
|
||||
var installButtons = this.element.querySelectorAll(".button.install");
|
||||
for (let i = 0; i < installButtons.length; i++) {
|
||||
installButtons[i].onclick = (e) => {this.onInstallClicked(e);}
|
||||
}
|
||||
|
||||
var uninstallButtons = this.element.querySelectorAll(".button.uninstall");
|
||||
for (let i = 0; i < uninstallButtons.length; i++) {
|
||||
uninstallButtons[i].onclick = (e) => {this.onUninstallClicked(e);}
|
||||
@ -47,24 +50,16 @@ class InstancesPage extends ManagerPage {
|
||||
stopButtons[i].onclick = (e) => {this.onStopClicked(e);}
|
||||
}
|
||||
|
||||
this.element.querySelector(".cancel").addEventListener("click", (e) => this.onCancelClicked(e));
|
||||
|
||||
super.render();
|
||||
}
|
||||
|
||||
async onEditClicked(e) {
|
||||
this.getClickedInstance(e).then((instance) => {
|
||||
instance.webserverOnline || instance.backendOnline? showErrorPopup("Error, the selected Olympus instance is currently active, please stop Olympus before editing it!") :
|
||||
this.setSelectedInstance(instance);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async onStartServerClicked(e) {
|
||||
e.target.closest(".collapse").classList.add("loading");
|
||||
this.getClickedInstance(e).then((instance) => instance.startServer());
|
||||
}
|
||||
|
||||
async onStartClientClicked(e) {
|
||||
e.target.closest(".collapse").classList.add("loading");
|
||||
this.getClickedInstance(e).then(instance => instance.startClient());
|
||||
}
|
||||
|
||||
@ -76,6 +71,30 @@ class InstancesPage extends ManagerPage {
|
||||
this.getClickedInstance(e).then((instance) => instance.stop());
|
||||
}
|
||||
|
||||
async onEditClicked(e) {
|
||||
this.getClickedInstance(e).then((instance) => {
|
||||
if (instance.webserverOnline || instance.backendOnline) {
|
||||
showErrorPopup("Error, the selected Olympus instance is currently active, please stop Olympus before editing it!")
|
||||
} else {
|
||||
this.manager.options.activeInstance = instance;
|
||||
this.manager.options.install = false;
|
||||
this.manager.options.singleInstance = false;
|
||||
this.hide();
|
||||
this.manager.typePage.show(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async onInstallClicked(e) {
|
||||
this.getClickedInstance(e).then((instance) => {
|
||||
this.manager.options.activeInstance = instance;
|
||||
this.manager.options.install = true;
|
||||
this.manager.options.singleInstance = false;
|
||||
this.hide();
|
||||
this.manager.typePage.show(this);
|
||||
});
|
||||
}
|
||||
|
||||
async onUninstallClicked(e) {
|
||||
this.getClickedInstance(e).then((instance) => {
|
||||
instance.webserverOnline || instance.backendOnline? showErrorPopup("Error, the selected Olympus instance is currently active, please stop Olympus before uninstalling it!") : instance.uninstall();
|
||||
@ -90,8 +109,8 @@ class InstancesPage extends ManagerPage {
|
||||
});
|
||||
}
|
||||
|
||||
show() {
|
||||
ejs.renderFile("./ejs/instances.ejs", this.options, {}, (err, str) => {
|
||||
show(previousPage) {
|
||||
ejs.renderFile("./ejs/instances.ejs", {...this.options, ...this.manager.options}, {}, (err, str) => {
|
||||
if (!err) {
|
||||
this.render(str);
|
||||
} else {
|
||||
@ -99,7 +118,51 @@ class InstancesPage extends ManagerPage {
|
||||
}
|
||||
});
|
||||
|
||||
super.show();
|
||||
var instanceDivs = this.element.querySelectorAll(`.option`);
|
||||
for (let i = 0; i < instanceDivs.length; i++) {
|
||||
var instanceDiv = instanceDivs[i];
|
||||
var instance = this.manager.options.instances.find((instance) => { return instance.folder === instanceDivs[i].dataset.folder;})
|
||||
if (instance) {
|
||||
instanceDiv.querySelector(".button.install").classList.toggle("hide", instance.installed);
|
||||
instanceDiv.querySelector(".button.start").classList.toggle("hide", !instance.installed)
|
||||
instanceDiv.querySelector(".button.uninstall").classList.toggle("hide", !instance.installed)
|
||||
instanceDiv.querySelector(".button.edit").classList.toggle("hide", !instance.installed)
|
||||
}
|
||||
}
|
||||
|
||||
super.show(previousPage);
|
||||
}
|
||||
|
||||
update() {
|
||||
|
||||
var instanceDivs = this.element.querySelectorAll(`.option`);
|
||||
for (let i = 0; i < instanceDivs.length; i++) {
|
||||
var instance = this.manager.options.instances.find((instance) => { return instance.folder === instanceDivs[i].dataset.folder;})
|
||||
if (instance && instance.installed) {
|
||||
var instanceDiv = instanceDivs[i];
|
||||
if (instanceDiv.querySelector(".webserver.online") !== null) {
|
||||
instanceDiv.querySelector(".webserver.online").classList.toggle("hide", !instance.webserverOnline)
|
||||
instanceDiv.querySelector(".webserver.offline").classList.toggle("hide", instance.webserverOnline)
|
||||
instanceDiv.querySelector(".backend.online").classList.toggle("hide", !instance.backendOnline)
|
||||
instanceDiv.querySelector(".backend.offline").classList.toggle("hide", instance.backendOnline)
|
||||
|
||||
if (this.backendOnline) {
|
||||
instanceDiv.querySelector(".fps .data").innerText = instance.fps;
|
||||
instanceDiv.querySelector(".load .data").innerText = instance.load;
|
||||
}
|
||||
|
||||
instanceDiv.querySelector(".button.start").classList.toggle("hide", instance.webserverOnline)
|
||||
instanceDiv.querySelector(".button.uninstall").classList.toggle("hide", instance.webserverOnline)
|
||||
instanceDiv.querySelector(".button.edit").classList.toggle("hide", instance.webserverOnline)
|
||||
instanceDiv.querySelector(".button.open-browser").classList.toggle("hide", !instance.webserverOnline)
|
||||
instanceDiv.querySelector(".button.stop").classList.toggle("hide", !instance.webserverOnline)
|
||||
|
||||
if (this.webserverOnline)
|
||||
instanceDiv.querySelector(".button.start").classList.remove("loading")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,264 +1,197 @@
|
||||
const MenuPage = require("./menu");
|
||||
const InstallationsPage = require('./installations');
|
||||
const ConnectionsPage = require('./connections');
|
||||
const PasswordsPage = require('./passwords');
|
||||
const ResultPage = require('./result');
|
||||
const InstancesPage = require('./instances');
|
||||
const path = require("path")
|
||||
const fs = require("fs");
|
||||
|
||||
const DCSInstance = require('./dcsinstance');
|
||||
const { showErrorPopup, showWaitPopup } = require('./popup');
|
||||
const { showErrorPopup, showWaitPopup, showConfirmPopup } = require('./popup');
|
||||
const { fixInstances } = require('./filesystem');
|
||||
const { logger } = require("./filesystem")
|
||||
const path = require("path")
|
||||
|
||||
const ManagerPage = require("./managerpage");
|
||||
const WizardPage = require("./wizardpage");
|
||||
|
||||
class Manager {
|
||||
simplified = true;
|
||||
options = {
|
||||
logLocation: path.join(__dirname, "..", "manager.log"),
|
||||
configLoaded: false
|
||||
};
|
||||
|
||||
welcomePage = null;
|
||||
folderPage = null;
|
||||
typePage = null;
|
||||
connectionsPage = null;
|
||||
passwordsPage = null;
|
||||
resultPage = null;
|
||||
instancesPage = null;
|
||||
|
||||
constructor() {
|
||||
|
||||
}
|
||||
document.addEventListener("signal", (ev) => {
|
||||
const callback = ev.detail.callback;
|
||||
const params = ev.detail.params;
|
||||
try {
|
||||
eval(`this.${callback}(${params})`)
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async start() {
|
||||
/* Get the list of DCS instances */
|
||||
var instances = await DCSInstance.getInstances();
|
||||
|
||||
/* If there is only 1 DCS Instance and Olympus is not installed in it, go straight to the installation page (since there is nothing else to do) */
|
||||
this.simplified = instances.length === 1 && !instances[0].installed;
|
||||
|
||||
document.getElementById("loader").classList.add("hide");
|
||||
|
||||
/* Check if there are corrupted or outdate instances */
|
||||
if (instances.some((instance) => {
|
||||
return instance.installed && instance.error;
|
||||
})) {
|
||||
/* Ask the user for confirmation */
|
||||
showErrorPopup("One or more Olympus instances are corrupted or need updating. Press Close to fix this.", async () => {
|
||||
showWaitPopup("Please wait while your instances are being fixed.")
|
||||
fixInstances(instances.filter((instance) => {
|
||||
return instance.installed && instance.error;
|
||||
})).then(
|
||||
() => { location.reload() },
|
||||
(err) => {
|
||||
logger.error(err);
|
||||
showErrorPopup(`An error occurred while trying to fix your installations. Please reinstall Olympus manually. <br><br> You can find more info in ${path.join(__dirname, "..", "manager.log")}`);
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/* Check which buttons should be enabled */
|
||||
const installEnabled = true;
|
||||
const manageEnabled = instances.some((instance) => { return instance.installed; });
|
||||
|
||||
/* Menu */
|
||||
var menuPage = new MenuPage();
|
||||
menuPage.options = {
|
||||
...menuPage.options,
|
||||
installEnabled: installEnabled,
|
||||
manageEnabled: manageEnabled
|
||||
}
|
||||
/* When the install button is clicked go the installation page */
|
||||
menuPage.onInstallClicked = (e) => {
|
||||
menuPage.hide();
|
||||
installationsPage.show();
|
||||
}
|
||||
/* When the manage button is clicked go to the instances page in "manage mode" (i.e. manage = true) */
|
||||
menuPage.onManageClicked = (e) => {
|
||||
menuPage.hide();
|
||||
instancesPage.show();
|
||||
}
|
||||
|
||||
/* Installations */
|
||||
var installationsPage = new InstallationsPage();
|
||||
installationsPage.options = {
|
||||
...installationsPage.options,
|
||||
instances: instances
|
||||
}
|
||||
installationsPage.setSelectedInstance = (activeInstance) => {
|
||||
/* Set the active options for the pages */
|
||||
const options = {
|
||||
instance: activeInstance,
|
||||
simplified: this.simplified,
|
||||
install: true
|
||||
/* Check if the options file exists */
|
||||
if (fs.existsSync("options.json")) {
|
||||
/* Load the options from the json file */
|
||||
try {
|
||||
this.options = {...this.options, ...JSON.parse(fs.readFileSync("options.json"))};
|
||||
this.options.configLoaded = true;
|
||||
} catch (e) {
|
||||
logger.error(`An error occurred while reading the options.json file: ${e}`);
|
||||
}
|
||||
connectionsPage.options = {
|
||||
...connectionsPage.options,
|
||||
...options
|
||||
}
|
||||
|
||||
if (!this.options.configLoaded) {
|
||||
/* Hide the loading page */
|
||||
document.getElementById("loader").classList.add("hide");
|
||||
|
||||
/* Show page to select basic vs expert mode */
|
||||
this.welcomePage = new ManagerPage(this, "./ejs/welcome.ejs");
|
||||
this.welcomePage.show();
|
||||
}
|
||||
else {
|
||||
document.getElementById("header").classList.remove("hide");
|
||||
|
||||
/* Initialize mode switching */
|
||||
if (this.options.mode === "basic") {
|
||||
document.getElementById("switch-mode").innerText = "Expert mode";
|
||||
document.getElementById("switch-mode").onclick = () => { this.switchMode("expert"); }
|
||||
}
|
||||
passwordsPage.options = {
|
||||
...passwordsPage.options,
|
||||
...options
|
||||
}
|
||||
resultPage.options = {
|
||||
...resultPage.options,
|
||||
...options
|
||||
else {
|
||||
document.getElementById("switch-mode").innerText = "Basic mode";
|
||||
document.getElementById("switch-mode").onclick = () => { this.switchMode("basic"); }
|
||||
}
|
||||
|
||||
/* Show the connections page */
|
||||
installationsPage.hide();
|
||||
connectionsPage.show();
|
||||
/* Get the list of DCS instances */
|
||||
this.options.instances = await DCSInstance.getInstances();
|
||||
|
||||
connectionsPage.onBackClicked = (e) => {
|
||||
/* Show the installation page */
|
||||
connectionsPage.hide();
|
||||
installationsPage.show();
|
||||
}
|
||||
}
|
||||
installationsPage.onCancelClicked = (e) => {
|
||||
/* Go back to the main menu */
|
||||
installationsPage.hide();
|
||||
menuPage.show();
|
||||
}
|
||||
|
||||
/* Instances */
|
||||
var instancesPage = new InstancesPage();
|
||||
instancesPage.options = {
|
||||
...instancesPage.options,
|
||||
instances: instances.filter((instance) => { return instance.installed; })
|
||||
}
|
||||
instancesPage.setSelectedInstance = (activeInstance) => {
|
||||
/* Set the active options for the pages */
|
||||
const options = {
|
||||
instance: activeInstance,
|
||||
simplified: this.simplified,
|
||||
install: false
|
||||
}
|
||||
connectionsPage.options = {
|
||||
...connectionsPage.options,
|
||||
...options
|
||||
}
|
||||
passwordsPage.options = {
|
||||
...passwordsPage.options,
|
||||
...options
|
||||
}
|
||||
resultPage.options = {
|
||||
...resultPage.options,
|
||||
...options
|
||||
/* Check if there are corrupted or outdate instances */
|
||||
if (this.options.instances.some((instance) => {
|
||||
return instance.installed && instance.error;
|
||||
})) {
|
||||
/* Ask the user for confirmation */
|
||||
showConfirmPopup("<div style='font-size: 18px; max-width: 100%;'>One or more of your Olympus instances are not up to date! </div> <br> <br> If you have just updated Olympus this is normal. <br> <br> Press Accept and the Manager will fix your instances for you. <br> Press Close to update your instances manually using the Installation Wizard", async () => {
|
||||
showWaitPopup("Please wait while your instances are being fixed.")
|
||||
fixInstances(this.options.instances.filter((instance) => {
|
||||
return instance.installed && instance.error;
|
||||
})).then(
|
||||
() => { location.reload() },
|
||||
(err) => {
|
||||
logger.error(err);
|
||||
showErrorPopup(`An error occurred while trying to fix your installations. Please reinstall Olympus manually. <br><br> You can find more info in ${path.join(__dirname, "..", "manager.log")}`);
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/* Show the connections page */
|
||||
instancesPage.hide();
|
||||
connectionsPage.show();
|
||||
this.options.installEnabled = true;
|
||||
this.options.editEnabled = this.options.instances.find(instance => instance.installed);
|
||||
this.options.uninstallEnabled = this.options.instances.find(instance => instance.installed);
|
||||
|
||||
connectionsPage.onBackClicked = (e) => {
|
||||
/* Show the instances page */
|
||||
connectionsPage.hide();
|
||||
instancesPage.show();
|
||||
}
|
||||
}
|
||||
instancesPage.onCancelClicked = (e) => {
|
||||
/* Go back to the main menu */
|
||||
instancesPage.hide();
|
||||
menuPage.show();
|
||||
}
|
||||
/* Hide the loading page */
|
||||
document.getElementById("loader").classList.add("hide");
|
||||
|
||||
/* Connections */
|
||||
var connectionsPage = new ConnectionsPage();
|
||||
connectionsPage.onNextClicked = async (e) => {
|
||||
let activeInstance = connectionsPage.options.instance;
|
||||
if (activeInstance) {
|
||||
/* Check that the selected ports are free before proceeding */
|
||||
if (await activeInstance.checkClientPort(activeInstance.clientPort) && await activeInstance.checkBackendPort(activeInstance.backendPort)) {
|
||||
connectionsPage.hide();
|
||||
passwordsPage.show();
|
||||
} else {
|
||||
showErrorPopup("Please make sure the selected ports are not already in use.")
|
||||
}
|
||||
this.options.singleInstance = this.options.instances.length === 1;
|
||||
|
||||
/* Create all the HTML pages */
|
||||
this.menuPage = new ManagerPage(this, "./ejs/menu.ejs");
|
||||
this.folderPage = new WizardPage(this, "./ejs/installation.ejs");
|
||||
this.typePage = new WizardPage(this, "./ejs/type.ejs");
|
||||
//this.connectionsPage = new ConnectionsPage(this);
|
||||
//this.passwordsPage = new PasswordsPage(this);
|
||||
//this.resultPage = new ResultPage(this);
|
||||
//this.instancesPage = new InstancesPage(this);
|
||||
|
||||
if (this.options.mode === "basic") {
|
||||
/* In basic mode no dashboard is shown */
|
||||
this.menuPage.show();
|
||||
} else {
|
||||
showErrorPopup(`An error has occurred, please restart the Olympus Manager. <br><br> You can find more info in ${path.join(__dirname, "..", "manager.log")}`)
|
||||
/* In Expert mode we go directly to the dashboard */
|
||||
this.instancesPage.show();
|
||||
}
|
||||
}
|
||||
connectionsPage.onCancelClicked = (e) => {
|
||||
/* Go back to the main menu */
|
||||
connectionsPage.hide();
|
||||
menuPage.show();
|
||||
}
|
||||
|
||||
/* Passwords */
|
||||
var passwordsPage = new PasswordsPage();
|
||||
passwordsPage.onBackClicked = (e) => {
|
||||
/* Go back to the connections page */
|
||||
let activeInstance = connectionsPage.options.instance;
|
||||
if (activeInstance) {
|
||||
passwordsPage.hide();
|
||||
connectionsPage.show();
|
||||
} else {
|
||||
showErrorPopup(`An error has occurred, please restart the Olympus Manager. <br><br> You can find more info in ${path.join(__dirname, "..", "manager.log")}`)
|
||||
}
|
||||
}
|
||||
passwordsPage.onNextClicked = (e) => {
|
||||
let activeInstance = connectionsPage.options.instance;
|
||||
if (activeInstance) {
|
||||
/* Check that all the passwords have been set */
|
||||
if (activeInstance.gameMasterPassword === "" || activeInstance.blueCommanderPassword === "" || activeInstance.redCommanderPassword === "") {
|
||||
showErrorPopup("Please fill all the password inputs.")
|
||||
}
|
||||
else if (activeInstance.gameMasterPassword === activeInstance.blueCommanderPassword || activeInstance.blueCommanderPassword === activeInstance.redCommanderPassword || activeInstance.gameMasterPassword === activeInstance.redCommanderPassword) {
|
||||
showErrorPopup("All the passwords must be different from each other.")
|
||||
} else {
|
||||
passwordsPage.hide();
|
||||
resultPage.show();
|
||||
resultPage.startInstallation();
|
||||
}
|
||||
} else {
|
||||
showErrorPopup(`An error has occurred, please restart the Olympus Manager. <br><br> You can find more info in ${path.join(__dirname, "..", "manager.log")}`)
|
||||
}
|
||||
|
||||
}
|
||||
passwordsPage.onCancelClicked = (e) => {
|
||||
/* Go back to the main menu */
|
||||
passwordsPage.hide();
|
||||
menuPage.show();
|
||||
}
|
||||
|
||||
/* Result */
|
||||
var resultPage = new ResultPage({logLocation: path.join(__dirname, "..", "manager.log")});
|
||||
resultPage.onBackClicked = (e) => {
|
||||
/* Reload the page to apply changes */
|
||||
resultPage.hide();
|
||||
location.reload();
|
||||
}
|
||||
resultPage.onCancelClicked = (e) => {
|
||||
/* Reload the page to apply changes */
|
||||
resultPage.hide();
|
||||
location.reload();
|
||||
}
|
||||
|
||||
/* Create all the HTML pages */
|
||||
document.body.appendChild(menuPage.getElement());
|
||||
document.body.appendChild(installationsPage.getElement());
|
||||
document.body.appendChild(instancesPage.getElement());
|
||||
document.body.appendChild(connectionsPage.getElement());
|
||||
document.body.appendChild(passwordsPage.getElement());
|
||||
document.body.appendChild(resultPage.getElement());
|
||||
|
||||
/* In simplified mode we directly show the connections page */
|
||||
if (this.simplified) {
|
||||
const options = {
|
||||
instance: instances[0],
|
||||
simplified: this.simplified,
|
||||
install: true
|
||||
}
|
||||
connectionsPage.options = {
|
||||
...connectionsPage.options,
|
||||
...options
|
||||
}
|
||||
passwordsPage.options = {
|
||||
...passwordsPage.options,
|
||||
...options
|
||||
}
|
||||
resultPage.options = {
|
||||
...resultPage.options,
|
||||
...options
|
||||
}
|
||||
/* Show the connections page directly */
|
||||
instancesPage.hide();
|
||||
connectionsPage.show();
|
||||
} else {
|
||||
/* Show the main menu */
|
||||
menuPage.show();
|
||||
}
|
||||
}
|
||||
|
||||
getActiveInstance() {
|
||||
return this.options.activeInstance;
|
||||
}
|
||||
|
||||
createOptionsFile(mode) {
|
||||
try {
|
||||
fs.writeFileSync("options.json", JSON.stringify({mode: mode}));
|
||||
location.reload();
|
||||
} catch (e) {
|
||||
showErrorPopup(`A critical error occurred, check ${this.options.logLocation} for more info.`)
|
||||
}
|
||||
}
|
||||
|
||||
switchMode(newMode) {
|
||||
/* Change the mode in the options.json and reload the page */
|
||||
var options = JSON.parse(fs.readFileSync("options.json"));
|
||||
options.mode = newMode;
|
||||
fs.writeFileSync("options.json", JSON.stringify(options));
|
||||
location.reload();
|
||||
}
|
||||
|
||||
/************************************************/
|
||||
/* CALLBACKS */
|
||||
/************************************************/
|
||||
/* Switch to basic mode */
|
||||
onBasicClicked() {
|
||||
this.createOptionsFile("basic");
|
||||
}
|
||||
|
||||
/* Switch to expert mode */
|
||||
onExpertClicked() {
|
||||
this.createOptionsFile("expert");
|
||||
}
|
||||
|
||||
/* When the install button is clicked go the installation page */
|
||||
onInstallClicked() {
|
||||
this.options.install = true;
|
||||
|
||||
if (this.options.singleInstance) {
|
||||
this.options.activeInstance = this.options.instances[0];
|
||||
|
||||
/* Show the type selection page */
|
||||
if (!this.options.activeInstance.installed) {
|
||||
this.menuPage.hide();
|
||||
this.typePage.show(this.menuPage);
|
||||
} else {
|
||||
showConfirmPopup("<div style='font-size: 18px; max-width: 100%'> Olympus is already installed in this instance! </div> If you click Accept, it will be installed again and all changes, e.g. custom databases or mods support, will be lost. Are you sure you want to continue?",
|
||||
() => {
|
||||
this.menuPage.hide();
|
||||
this.typePage.show(this.menuPage);
|
||||
}
|
||||
)
|
||||
}
|
||||
} else {
|
||||
/* Show the folder selection page */
|
||||
this.menuPage.hide();
|
||||
this.folderPage.show(this.menuPage);
|
||||
}
|
||||
}
|
||||
|
||||
/* When the edit button is clicked go to the instances page */
|
||||
onEditClicked() {
|
||||
this.hide();
|
||||
this.options.install = false;
|
||||
|
||||
if (this.options.singleInstance) {
|
||||
this.options.activeInstance = this.options.instances[0];
|
||||
this.typePage.show(this);
|
||||
} else {
|
||||
this.folderPage.show(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
module.exports = Manager;
|
||||
15
manager/javascripts/managerfactory.js
Normal file
15
manager/javascripts/managerfactory.js
Normal file
@ -0,0 +1,15 @@
|
||||
var manager = null;
|
||||
|
||||
function getManager() {
|
||||
if (manager) {
|
||||
return manager;
|
||||
} else {
|
||||
const Manager = require("./manager");
|
||||
manager = new Manager();
|
||||
return manager;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getManager: getManager
|
||||
};
|
||||
@ -1,33 +1,54 @@
|
||||
class ManagerPage {
|
||||
element;
|
||||
options;
|
||||
const { logger } = require("./filesystem");
|
||||
const ejs = require('ejs')
|
||||
|
||||
constructor(options) {
|
||||
this.options = options ?? {};
|
||||
class ManagerPage {
|
||||
manager;
|
||||
ejsFile;
|
||||
element;
|
||||
options = {};
|
||||
previousPage;
|
||||
|
||||
constructor(manager, ejsFile) {
|
||||
this.manager = manager;
|
||||
this.element = document.createElement('div');
|
||||
this.element.classList.add("manager-page", "hide");
|
||||
this.ejsFile = ejsFile;
|
||||
document.body.appendChild(this.element);
|
||||
}
|
||||
|
||||
getElement() {
|
||||
return this.element;
|
||||
}
|
||||
|
||||
show() {
|
||||
show(previousPage) {
|
||||
ejs.renderFile(this.ejsFile, {...this.options, ...this.manager.options}, {}, (err, str) => {
|
||||
if (!err) {
|
||||
this.render(str);
|
||||
} else {
|
||||
logger.error(err);
|
||||
}
|
||||
});
|
||||
|
||||
this.element.classList.remove("hide");
|
||||
|
||||
if (previousPage !== undefined)
|
||||
this.previousPage = previousPage;
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.element.classList.add("hide");
|
||||
}
|
||||
|
||||
render() {
|
||||
render(str) {
|
||||
this.element.innerHTML = str;
|
||||
|
||||
/* Connect all the collapsable buttons */
|
||||
let buttons = document.querySelectorAll(".button.collapse");
|
||||
for (let i = 0; i < buttons.length; i++) {
|
||||
buttons[i].addEventListener("click", () => {
|
||||
buttons[i].classList.toggle("open");
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
const ManagerPage = require("./managerpage");
|
||||
const ejs = require('ejs')
|
||||
const { logger } = require("./filesystem")
|
||||
|
||||
class MenuPage extends ManagerPage {
|
||||
onInstallClicked;
|
||||
onUpdateClicked;
|
||||
onManageClicked;
|
||||
|
||||
constructor(options) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
render(str) {
|
||||
const element = this.getElement();
|
||||
element.innerHTML = str;
|
||||
|
||||
element.querySelector(".install").addEventListener("click", (e) => this.onInstallClicked(e));
|
||||
element.querySelector(".manage").addEventListener("click", (e) => this.onManageClicked(e));
|
||||
|
||||
super.render();
|
||||
}
|
||||
|
||||
show() {
|
||||
this.instance = this.options.instance;
|
||||
|
||||
ejs.renderFile("./ejs/menu.ejs", this.options, {}, (err, str) => {
|
||||
if (!err) {
|
||||
this.render(str);
|
||||
} else {
|
||||
logger.error(err);
|
||||
}
|
||||
});
|
||||
|
||||
super.show();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MenuPage;
|
||||
@ -3,38 +3,23 @@ const ejs = require('ejs')
|
||||
const { logger } = require("./filesystem")
|
||||
|
||||
class PasswordsPage extends ManagerPage {
|
||||
onBackClicked;
|
||||
onNextClicked;
|
||||
onCancelClicked;
|
||||
|
||||
constructor(options) {
|
||||
super(options);
|
||||
constructor(manager, options) {
|
||||
super(manager, options);
|
||||
}
|
||||
|
||||
render(str) {
|
||||
const element = this.getElement();
|
||||
element.innerHTML = str;
|
||||
|
||||
if (this.element.querySelector(".back"))
|
||||
this.element.querySelector(".back").addEventListener("click", (e) => this.onBackClicked(e));
|
||||
|
||||
if (this.element.querySelector(".next"))
|
||||
this.element.querySelector(".next").addEventListener("click", (e) => this.onNextClicked(e));
|
||||
|
||||
if (this.element.querySelector(".cancel"))
|
||||
this.element.querySelector(".cancel").addEventListener("click", (e) => this.onCancelClicked(e));
|
||||
|
||||
this.element.querySelector(".game-master").querySelector("input").addEventListener("change", async (e) => { this.instance.setGameMasterPassword(e.target.value); })
|
||||
this.element.querySelector(".blue-commander").querySelector("input").addEventListener("change", async (e) => { this.instance.setBlueCommanderPassword(e.target.value); })
|
||||
this.element.querySelector(".red-commander").querySelector("input").addEventListener("change", async (e) => { this.instance.setRedCommanderPassword(e.target.value); })
|
||||
this.element.querySelector(".game-master").querySelector("input").addEventListener("change", async (e) => { this.manager.getActiveInstance().setGameMasterPassword(e.target.value); })
|
||||
this.element.querySelector(".blue-commander").querySelector("input").addEventListener("change", async (e) => { this.manager.getActiveInstance().setBlueCommanderPassword(e.target.value); })
|
||||
this.element.querySelector(".red-commander").querySelector("input").addEventListener("change", async (e) => { this.manager.getActiveInstance().setRedCommanderPassword(e.target.value); })
|
||||
|
||||
super.render();
|
||||
}
|
||||
|
||||
show() {
|
||||
this.instance = this.options.instance;
|
||||
|
||||
ejs.renderFile("./ejs/passwords.ejs", this.options, {}, (err, str) => {
|
||||
show(previousPage) {
|
||||
ejs.renderFile("./ejs/passwords.ejs", {...this.options, ...this.manager.options}, {}, (err, str) => {
|
||||
if (!err) {
|
||||
this.render(str);
|
||||
} else {
|
||||
@ -42,7 +27,18 @@ class PasswordsPage extends ManagerPage {
|
||||
}
|
||||
});
|
||||
|
||||
super.show();
|
||||
super.show(previousPage);
|
||||
}
|
||||
|
||||
onNextClicked() {
|
||||
this.hide();
|
||||
this.manager.resultPage.show();
|
||||
this.manager.resultPage.startInstallation();
|
||||
}
|
||||
|
||||
onCancelClicked() {
|
||||
this.hide();
|
||||
this.manager.menuPage.show()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,24 @@
|
||||
// TODO: we can probably refactor this to be a bit cleaner
|
||||
|
||||
function showInfoPopup(message, onCloseCallback) {
|
||||
document.getElementById("grayout").classList.remove("hide");
|
||||
document.getElementById("popup").classList.remove("hide");
|
||||
document.getElementById("popup").querySelector(".error").classList.add("hide");
|
||||
document.getElementById("popup").querySelector(".wait").classList.add("hide");
|
||||
document.getElementById("popup").querySelector(".confirm").classList.remove("hide");
|
||||
document.getElementById("popup").querySelector(".close-popup").classList.remove("hide");
|
||||
document.getElementById("popup").querySelector(".accept-popup").classList.add("hide");
|
||||
|
||||
/* Not using event listeners to make sure we only have one callback */
|
||||
document.getElementById("popup").querySelector(".close-popup").onclick = (e) => {
|
||||
hidePopup();
|
||||
if (onCloseCallback)
|
||||
onCloseCallback();
|
||||
}
|
||||
document.getElementById("popup").querySelector(".content").innerHTML = message;
|
||||
}
|
||||
|
||||
|
||||
function showErrorPopup(message, onCloseCallback) {
|
||||
document.getElementById("grayout").classList.remove("hide");
|
||||
document.getElementById("popup").classList.remove("hide");
|
||||
@ -61,6 +80,7 @@ function hidePopup() {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
showInfoPopup: showInfoPopup,
|
||||
showErrorPopup: showErrorPopup,
|
||||
showConfirmPopup: showConfirmPopup,
|
||||
showWaitPopup: showWaitPopup,
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
const Manager = require('./manager');
|
||||
|
||||
const contextBridge = require('electron').contextBridge;
|
||||
const ipcRenderer = require('electron').ipcRenderer;
|
||||
const { exec, spawn } = require("child_process");
|
||||
@ -10,7 +8,8 @@ const https = require('follow-redirects').https;
|
||||
const fs = require('fs');
|
||||
const AdmZip = require("adm-zip");
|
||||
const { Octokit } = require('octokit');
|
||||
const { logger } = require("./filesystem")
|
||||
const { logger } = require("./filesystem");
|
||||
const { getManager } = require('./managerFactory');
|
||||
|
||||
const VERSION = "{{OLYMPUS_VERSION_NUMBER}}";
|
||||
logger.log(`Running in ${__dirname}`);
|
||||
@ -257,15 +256,12 @@ contextBridge.exposeInMainWorld(
|
||||
}
|
||||
});
|
||||
|
||||
/* New instance of the manager app */
|
||||
const manager = new Manager();
|
||||
|
||||
/* On content loaded */
|
||||
window.addEventListener('DOMContentLoaded', async () => {
|
||||
/* Compute the height of the content page */
|
||||
computePagesHeight();
|
||||
document.getElementById("loader").classList.remove("hide");
|
||||
await manager.start();
|
||||
await getManager().start();
|
||||
/* Compute the height of the content page to account for the pages created by the manager*/
|
||||
computePagesHeight();
|
||||
|
||||
@ -273,7 +269,8 @@ window.addEventListener('DOMContentLoaded', async () => {
|
||||
var links = document.querySelectorAll(".link");
|
||||
for (let i = 0; i < links.length; i++) {
|
||||
links[i].addEventListener("click", (e) => {
|
||||
exec("start " + e.target.dataset.link);
|
||||
if (e.target.dataset.link)
|
||||
exec("start " + e.target.dataset.link);
|
||||
})
|
||||
}
|
||||
})
|
||||
@ -298,4 +295,4 @@ function computePagesHeight() {
|
||||
ipcRenderer.on("check-version", () => {
|
||||
/* Check if a new version is available */
|
||||
checkVersion();
|
||||
})
|
||||
})
|
||||
|
||||
@ -4,27 +4,19 @@ const ejs = require('ejs')
|
||||
const { logger } = require("./filesystem")
|
||||
|
||||
class ResultPage extends ManagerPage {
|
||||
onBackClicked;
|
||||
onNextClicked;
|
||||
onCancelClicked;
|
||||
|
||||
constructor(options) {
|
||||
super(options);
|
||||
constructor(manager, options) {
|
||||
super(manager, options);
|
||||
}
|
||||
|
||||
render(str) {
|
||||
const element = this.getElement();
|
||||
element.innerHTML = str;
|
||||
|
||||
this.element.querySelector(".back").addEventListener("click", (e) => this.onBackClicked(e));
|
||||
|
||||
super.render();
|
||||
}
|
||||
|
||||
show() {
|
||||
this.instance = this.options.instance;
|
||||
|
||||
ejs.renderFile("./ejs/result.ejs", this.options, {}, (err, str) => {
|
||||
show(previousPage) {
|
||||
ejs.renderFile("./ejs/result.ejs", {...this.options, ...this.manager.options}, {}, (err, str) => {
|
||||
if (!err) {
|
||||
this.render(str);
|
||||
} else {
|
||||
@ -32,14 +24,18 @@ class ResultPage extends ManagerPage {
|
||||
}
|
||||
});
|
||||
|
||||
super.show();
|
||||
super.show(previousPage);
|
||||
}
|
||||
|
||||
onBackClicked() {
|
||||
location.reload();
|
||||
}
|
||||
|
||||
/** Installation is performed by using an then chain of async functions. Installation is aborted on any error along the chain
|
||||
*
|
||||
*/
|
||||
startInstallation() {
|
||||
installHooks(this.instance.folder).then(
|
||||
installHooks(this.manager.getActiveInstance().folder).then(
|
||||
() => {
|
||||
this.applyStepSuccess(".hook");
|
||||
},
|
||||
@ -47,7 +43,7 @@ class ResultPage extends ManagerPage {
|
||||
this.applyStepFailure(".hook");
|
||||
return Promise.reject(err);
|
||||
}
|
||||
).then(() => installMod(this.instance.folder, this.instance.name)).then(
|
||||
).then(() => installMod(this.manager.getActiveInstance().folder, this.manager.getActiveInstance().name)).then(
|
||||
() => {
|
||||
this.applyStepSuccess(".mod");
|
||||
},
|
||||
@ -55,7 +51,7 @@ class ResultPage extends ManagerPage {
|
||||
this.applyStepFailure(".mod");
|
||||
return Promise.reject(err);
|
||||
}
|
||||
).then(() => installJSON(this.instance.folder)).then(
|
||||
).then(() => installJSON(this.manager.getActiveInstance().folder)).then(
|
||||
() => {
|
||||
this.applyStepSuccess(".json");
|
||||
},
|
||||
@ -63,7 +59,7 @@ class ResultPage extends ManagerPage {
|
||||
this.applyStepFailure(".json");
|
||||
return Promise.reject(err);
|
||||
}
|
||||
).then(() => applyConfiguration(this.instance.folder, this.instance)).then(
|
||||
).then(() => applyConfiguration(this.manager.getActiveInstance().folder, this.manager.getActiveInstance())).then(
|
||||
() => {
|
||||
this.applyStepSuccess(".config");
|
||||
},
|
||||
@ -71,7 +67,7 @@ class ResultPage extends ManagerPage {
|
||||
this.applyStepFailure(".config");
|
||||
return Promise.reject(err);
|
||||
}
|
||||
).then(() => installShortCuts(this.instance.folder, this.instance.name)).then(
|
||||
).then(() => installShortCuts(this.manager.getActiveInstance().folder, this.manager.getActiveInstance().name)).then(
|
||||
() => {
|
||||
this.applyStepSuccess(".shortcuts");
|
||||
},
|
||||
|
||||
49
manager/javascripts/type.js
Normal file
49
manager/javascripts/type.js
Normal file
@ -0,0 +1,49 @@
|
||||
const ManagerPage = require("./managerpage");
|
||||
const ejs = require('ejs')
|
||||
const { logger } = require("./filesystem")
|
||||
|
||||
/** Type of install page, allows the user to select single player or multi player installation
|
||||
*
|
||||
*/
|
||||
class TypePage extends ManagerPage {
|
||||
constructor(manager, options) {
|
||||
super(manager, options);
|
||||
}
|
||||
|
||||
render(str) {
|
||||
const element = this.getElement();
|
||||
element.innerHTML = str;
|
||||
|
||||
this.element.querySelector(".singleplayer").addEventListener("click", (e) => this.onOptionSelected(false));
|
||||
this.element.querySelector(".multiplayer").addEventListener("click", (e) => this.onOptionSelected(true));
|
||||
|
||||
super.render();
|
||||
}
|
||||
|
||||
show(previousPage) {
|
||||
ejs.renderFile("./ejs/type.ejs", {...this.options, ...this.manager.options}, {}, (err, str) => {
|
||||
if (!err) {
|
||||
this.render(str);
|
||||
|
||||
} else {
|
||||
logger.error(err);
|
||||
}
|
||||
});
|
||||
|
||||
super.show(previousPage);
|
||||
}
|
||||
|
||||
onCancelClicked() {
|
||||
this.hide();
|
||||
this.manager.menuPage.show()
|
||||
}
|
||||
|
||||
onOptionSelected(multiplayer) {
|
||||
this.manager.options.multiplayer = multiplayer;
|
||||
this.hide();
|
||||
this.manager.connectionsPage.options.selectAutoOrManual = true;
|
||||
this.manager.connectionsPage.show(this);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TypePage;
|
||||
53
manager/javascripts/wizardpage.js
Normal file
53
manager/javascripts/wizardpage.js
Normal file
@ -0,0 +1,53 @@
|
||||
const ManagerPage = require("./managerpage");
|
||||
const ejs = require('ejs')
|
||||
|
||||
class WizardPage extends ManagerPage {
|
||||
contentEjsFile;
|
||||
|
||||
constructor(manager, contentEjsFile) {
|
||||
super(manager, './ejs/wizard.ejs');
|
||||
this.contentEjsFile = contentEjsFile;
|
||||
}
|
||||
|
||||
render(str) {
|
||||
super.render(str);
|
||||
|
||||
/* Connect the back, next and cancel buttons */
|
||||
if (this.element.querySelector(".back"))
|
||||
this.element.querySelector(".back").addEventListener("click", (e) => this.onBackClicked(e));
|
||||
|
||||
if (this.element.querySelector(".next"))
|
||||
this.element.querySelector(".next").addEventListener("click", (e) => this.onNextClicked(e));
|
||||
|
||||
if (this.element.querySelector(".cancel"))
|
||||
this.element.querySelector(".cancel").addEventListener("click", (e) => this.onCancelClicked(e));
|
||||
|
||||
ejs.renderFile(this.contentEjsFile, {...this.options, ...this.manager.options}, {}, (err, str) => {
|
||||
if (!err) {
|
||||
this.element.querySelector(".content").innerHTML = str;
|
||||
} else {
|
||||
logger.error(err);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
onBackClicked() {
|
||||
console.log(this.previousPage)
|
||||
this.hide();
|
||||
this.previousPage.show()
|
||||
}
|
||||
|
||||
onCancelClicked() {
|
||||
this.hide();
|
||||
if (this.manager.options.mode === "basic") {
|
||||
/* In basic mode no dashboard is shown */
|
||||
this.manager.menuPage.show();
|
||||
} else {
|
||||
/* In Expert mode we go directly to the dashboard */
|
||||
this.manager.instancesPage.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WizardPage;
|
||||
317
manager/manager.log
Normal file
317
manager/manager.log
Normal file
@ -0,0 +1,317 @@
|
||||
======================= New log starting at Thu Jan 11 2024 16:07:31 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
Development build detected, skipping version checks...
|
||||
======================= New log starting at Thu Jan 11 2024 16:11:52 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
======================= New log starting at Thu Jan 11 2024 16:11:54 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
======================= New log starting at Thu Jan 11 2024 16:11:56 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
======================= New log starting at Thu Jan 11 2024 16:13:03 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
======================= New log starting at Thu Jan 11 2024 16:13:31 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
======================= New log starting at Thu Jan 11 2024 16:13:41 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
======================= New log starting at Thu Jan 11 2024 16:13:48 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
======================= New log starting at Thu Jan 11 2024 16:23:11 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
ReferenceError: ./ejs/connections.ejs:32
|
||||
30| <div id="manager-connections">
|
||||
31| <div class="step-summary">
|
||||
>> 32| <div class="blue <%= !install || basic? 'hide': '' %>">User path</div>
|
||||
33| <div class="white">Ports and address</div>
|
||||
34| <div class="empty">Passwords</div>
|
||||
35| <div class="empty"> <%= install? 'Install': 'Update' %></div>
|
||||
|
||||
basic is not defined
|
||||
at eval ("./ejs/connections.ejs":12:38)
|
||||
at connections (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:703:17)
|
||||
at tryHandleCache (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:274:36)
|
||||
at exports.renderFile (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:491:10)
|
||||
at ConnectionsPage.show (D:\Documents\DCSOlympus\manager\javascripts\connections.js:41:13)
|
||||
at Manager.start (D:\Documents\DCSOlympus\manager\javascripts\manager.js:70:42)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
|
||||
at async D:\Documents\DCSOlympus\manager\javascripts\preload.js:268:5 {
|
||||
path: './ejs/connections.ejs'
|
||||
}
|
||||
======================= New log starting at Thu Jan 11 2024 16:24:03 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
ReferenceError: ./ejs/connections.ejs:32
|
||||
30| <div id="manager-connections">
|
||||
31| <div class="step-summary">
|
||||
>> 32| <div class="blue <%= !install || basic? 'hide': '' %>">User path</div>
|
||||
33| <div class="white">Ports and address</div>
|
||||
34| <div class="empty">Passwords</div>
|
||||
35| <div class="empty"> <%= install? 'Install': 'Update' %></div>
|
||||
|
||||
basic is not defined
|
||||
at eval ("./ejs/connections.ejs":12:38)
|
||||
at connections (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:703:17)
|
||||
at tryHandleCache (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:274:36)
|
||||
at exports.renderFile (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:491:10)
|
||||
at ConnectionsPage.show (D:\Documents\DCSOlympus\manager\javascripts\connections.js:41:13)
|
||||
at Manager.start (D:\Documents\DCSOlympus\manager\javascripts\manager.js:70:42)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
|
||||
at async D:\Documents\DCSOlympus\manager\javascripts\preload.js:268:5 {
|
||||
path: './ejs/connections.ejs'
|
||||
}
|
||||
======================= New log starting at Thu Jan 11 2024 16:24:25 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
ReferenceError: ./ejs/connections.ejs:32
|
||||
30| <div id="manager-connections">
|
||||
31| <div class="step-summary">
|
||||
>> 32| <div class="blue <%= !install || basic? 'hide': '' %>">User path</div>
|
||||
33| <div class="white">Ports and address</div>
|
||||
34| <div class="empty">Passwords</div>
|
||||
35| <div class="empty"> <%= install? 'Install': 'Update' %></div>
|
||||
|
||||
basic is not defined
|
||||
at eval ("./ejs/connections.ejs":12:38)
|
||||
at connections (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:703:17)
|
||||
at tryHandleCache (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:274:36)
|
||||
at exports.renderFile (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:491:10)
|
||||
at ConnectionsPage.show (D:\Documents\DCSOlympus\manager\javascripts\connections.js:41:13)
|
||||
at Manager.start (D:\Documents\DCSOlympus\manager\javascripts\manager.js:71:42)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
|
||||
at async D:\Documents\DCSOlympus\manager\javascripts\preload.js:268:5 {
|
||||
path: './ejs/connections.ejs'
|
||||
}
|
||||
======================= New log starting at Thu Jan 11 2024 16:24:45 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
ReferenceError: ./ejs/connections.ejs:32
|
||||
30| <div id="manager-connections">
|
||||
31| <div class="step-summary">
|
||||
>> 32| <div class="blue <%= !install || basic? 'hide': '' %>">User path</div>
|
||||
33| <div class="white">Ports and address</div>
|
||||
34| <div class="empty">Passwords</div>
|
||||
35| <div class="empty"> <%= install? 'Install': 'Update' %></div>
|
||||
|
||||
basic is not defined
|
||||
at eval ("./ejs/connections.ejs":12:38)
|
||||
at connections (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:703:17)
|
||||
at tryHandleCache (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:274:36)
|
||||
at exports.renderFile (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:491:10)
|
||||
at ConnectionsPage.show (D:\Documents\DCSOlympus\manager\javascripts\connections.js:41:13)
|
||||
at Manager.start (D:\Documents\DCSOlympus\manager\javascripts\manager.js:71:42)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
|
||||
at async D:\Documents\DCSOlympus\manager\javascripts\preload.js:268:5 {
|
||||
path: './ejs/connections.ejs'
|
||||
}
|
||||
======================= New log starting at Thu Jan 11 2024 16:25:20 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
ReferenceError: ./ejs/connections.ejs:32
|
||||
30| <div id="manager-connections">
|
||||
31| <div class="step-summary">
|
||||
>> 32| <div class="blue <%= !install || basic? 'hide': '' %>">User path</div>
|
||||
33| <div class="white">Ports and address</div>
|
||||
34| <div class="empty">Passwords</div>
|
||||
35| <div class="empty"> <%= install? 'Install': 'Update' %></div>
|
||||
|
||||
basic is not defined
|
||||
at eval ("./ejs/connections.ejs":12:38)
|
||||
at connections (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:703:17)
|
||||
at tryHandleCache (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:274:36)
|
||||
at exports.renderFile (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:491:10)
|
||||
at ConnectionsPage.show (D:\Documents\DCSOlympus\manager\javascripts\connections.js:41:13)
|
||||
at Manager.start (D:\Documents\DCSOlympus\manager\javascripts\manager.js:78:42)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
|
||||
at async D:\Documents\DCSOlympus\manager\javascripts\preload.js:268:5 {
|
||||
path: './ejs/connections.ejs'
|
||||
}
|
||||
======================= New log starting at Thu Jan 11 2024 16:28:55 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
ReferenceError: ./ejs/connections.ejs:52
|
||||
50| </span>
|
||||
51| <div>
|
||||
>> 52| <input type="number" min="1024" max="65535" value="<%= instance["clientPort"] %>">
|
||||
53| <img class="success hide">
|
||||
54| <div class="error hide">
|
||||
55| <img> <span>Port already in use</span>
|
||||
|
||||
instance is not defined
|
||||
at eval ("./ejs/connections.ejs":18:26)
|
||||
at connections (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:703:17)
|
||||
at tryHandleCache (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:274:36)
|
||||
at exports.renderFile (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:491:10)
|
||||
at ConnectionsPage.show (D:\Documents\DCSOlympus\manager\javascripts\connections.js:41:13)
|
||||
at Manager.start (D:\Documents\DCSOlympus\manager\javascripts\manager.js:78:42)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
|
||||
at async D:\Documents\DCSOlympus\manager\javascripts\preload.js:268:5 {
|
||||
path: './ejs/connections.ejs'
|
||||
}
|
||||
======================= New log starting at Thu Jan 11 2024 16:29:02 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
ReferenceError: ./ejs/connections.ejs:52
|
||||
50| </span>
|
||||
51| <div>
|
||||
>> 52| <input type="number" min="1024" max="65535" value="<%= instance["clientPort"] %>">
|
||||
53| <img class="success hide">
|
||||
54| <div class="error hide">
|
||||
55| <img> <span>Port already in use</span>
|
||||
|
||||
instance is not defined
|
||||
at eval ("./ejs/connections.ejs":18:26)
|
||||
at connections (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:703:17)
|
||||
at tryHandleCache (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:274:36)
|
||||
at exports.renderFile (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:491:10)
|
||||
at ConnectionsPage.show (D:\Documents\DCSOlympus\manager\javascripts\connections.js:41:13)
|
||||
at Manager.start (D:\Documents\DCSOlympus\manager\javascripts\manager.js:78:42)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
|
||||
at async D:\Documents\DCSOlympus\manager\javascripts\preload.js:268:5 {
|
||||
path: './ejs/connections.ejs'
|
||||
}
|
||||
======================= New log starting at Thu Jan 11 2024 16:31:06 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
ReferenceError: ./ejs/connections.ejs:52
|
||||
50| </span>
|
||||
51| <div>
|
||||
>> 52| <input type="number" min="1024" max="65535" value="<%= instance["clientPort"] %>">
|
||||
53| <img class="success hide">
|
||||
54| <div class="error hide">
|
||||
55| <img> <span>Port already in use</span>
|
||||
|
||||
instance is not defined
|
||||
at eval ("./ejs/connections.ejs":18:26)
|
||||
at connections (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:703:17)
|
||||
at tryHandleCache (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:274:36)
|
||||
at exports.renderFile (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:491:10)
|
||||
at ConnectionsPage.show (D:\Documents\DCSOlympus\manager\javascripts\connections.js:41:13)
|
||||
at Manager.start (D:\Documents\DCSOlympus\manager\javascripts\manager.js:77:42)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
|
||||
at async D:\Documents\DCSOlympus\manager\javascripts\preload.js:268:5 {
|
||||
path: './ejs/connections.ejs'
|
||||
}
|
||||
======================= New log starting at Thu Jan 11 2024 16:37:31 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
ReferenceError: ./ejs/connections.ejs:52
|
||||
50| </span>
|
||||
51| <div>
|
||||
>> 52| <input type="number" min="1024" max="65535" value="<%= instance["clientPort"] %>">
|
||||
53| <img class="success hide">
|
||||
54| <div class="error hide">
|
||||
55| <img> <span>Port already in use</span>
|
||||
|
||||
instance is not defined
|
||||
at eval ("./ejs/connections.ejs":18:26)
|
||||
at connections (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:703:17)
|
||||
at tryHandleCache (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:274:36)
|
||||
at exports.renderFile (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:491:10)
|
||||
at ConnectionsPage.show (D:\Documents\DCSOlympus\manager\javascripts\connections.js:38:13)
|
||||
at Manager.start (D:\Documents\DCSOlympus\manager\javascripts\manager.js:77:42)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
|
||||
at async D:\Documents\DCSOlympus\manager\javascripts\preload.js:268:5 {
|
||||
path: './ejs/connections.ejs'
|
||||
}
|
||||
======================= New log starting at Thu Jan 11 2024 16:38:57 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
======================= New log starting at Thu Jan 11 2024 16:39:52 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
======================= New log starting at Thu Jan 11 2024 16:41:14 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
======================= New log starting at Thu Jan 11 2024 16:41:25 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
======================= New log starting at Thu Jan 11 2024 16:41:48 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
======================= New log starting at Thu Jan 11 2024 16:42:27 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
======================= New log starting at Thu Jan 11 2024 16:42:52 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
======================= New log starting at Thu Jan 11 2024 16:43:06 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
======================= New log starting at Thu Jan 11 2024 16:43:24 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
Instance C:\Users\dpassoni\Saved Games\dcs.openbeta client port set to 3000
|
||||
Instance C:\Users\dpassoni\Saved Games\dcs.openbeta client port set to 3001
|
||||
======================= New log starting at Thu Jan 11 2024 16:54:16 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
======================= New log starting at Thu Jan 11 2024 16:54:21 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
Instance C:\Users\dpassoni\Saved Games\dcs.openbeta client port set to 3000
|
||||
Instance C:\Users\dpassoni\Saved Games\dcs.openbeta client port set to 3001
|
||||
ReferenceError: ./ejs/passwords.ejs:6
|
||||
4| <div id="manager-passwords">
|
||||
5| <div class="step-summary">
|
||||
>> 6| <div class="blue <%= !install || singleInstance? 'hide': '' %>">User path</div>
|
||||
7| <div class="blue">Ports and address</div>
|
||||
8| <div class="white">Passwords</div>
|
||||
9| <div class="empty"> <%= install? 'Install': 'Update' %></div>
|
||||
|
||||
install is not defined
|
||||
at eval ("./ejs/passwords.ejs":12:27)
|
||||
at passwords (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:703:17)
|
||||
at tryHandleCache (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:274:36)
|
||||
at exports.renderFile (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:491:10)
|
||||
at PasswordsPage.show (D:\Documents\DCSOlympus\manager\javascripts\passwords.js:35:13)
|
||||
at ConnectionsPage.onNextClicked (D:\Documents\DCSOlympus\manager\javascripts\connections.js:58:36)
|
||||
at HTMLDivElement.<anonymous> (D:\Documents\DCSOlympus\manager\javascripts\connections.js:21:87) {
|
||||
path: './ejs/passwords.ejs'
|
||||
}
|
||||
======================= New log starting at Thu Jan 11 2024 16:54:49 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
Instance C:\Users\dpassoni\Saved Games\dcs.openbeta client port set to 3000
|
||||
Instance C:\Users\dpassoni\Saved Games\dcs.openbeta client port set to 3001
|
||||
ReferenceError: ./ejs/passwords.ejs:44
|
||||
42| </div>
|
||||
43| </div>
|
||||
>> 44| <% if (!basic) { %>
|
||||
45| <div class="button cancel">
|
||||
46| <%= install? "Cancel installation": "Cancel editing" %>
|
||||
47| </div>
|
||||
|
||||
basic is not defined
|
||||
at eval ("./ejs/passwords.ejs":18:8)
|
||||
at passwords (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:703:17)
|
||||
at tryHandleCache (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:274:36)
|
||||
at exports.renderFile (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:491:10)
|
||||
at PasswordsPage.show (D:\Documents\DCSOlympus\manager\javascripts\passwords.js:35:13)
|
||||
at ConnectionsPage.onNextClicked (D:\Documents\DCSOlympus\manager\javascripts\connections.js:58:36)
|
||||
at HTMLDivElement.<anonymous> (D:\Documents\DCSOlympus\manager\javascripts\connections.js:21:87) {
|
||||
path: './ejs/passwords.ejs'
|
||||
}
|
||||
======================= New log starting at Thu Jan 11 2024 16:55:57 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
Instance C:\Users\dpassoni\Saved Games\dcs.openbeta client port set to 3000
|
||||
Instance C:\Users\dpassoni\Saved Games\dcs.openbeta client port set to 3001
|
||||
======================= New log starting at Fri Jan 12 2024 08:51:22 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
Development build detected, skipping version checks...
|
||||
Instance C:\Users\dpassoni\Saved Games\dcs.openbeta client port set to 3000
|
||||
Instance C:\Users\dpassoni\Saved Games\dcs.openbeta client port set to 3001
|
||||
======================= New log starting at Fri Jan 12 2024 08:53:17 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
Instance C:\Users\dpassoni\Saved Games\dcs.openbeta client port set to 3000
|
||||
Instance C:\Users\dpassoni\Saved Games\dcs.openbeta client port set to 3001
|
||||
======================= New log starting at Fri Jan 12 2024 08:53:42 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
Instance C:\Users\dpassoni\Saved Games\dcs.openbeta client port set to 3000
|
||||
Instance C:\Users\dpassoni\Saved Games\dcs.openbeta client port set to 3001
|
||||
ReferenceError: ./ejs/result.ejs:132
|
||||
130| <div>
|
||||
131| <span>
|
||||
>> 132| <%= instance.name %>
|
||||
133| </span>
|
||||
134| <span><img src="./icons/folder-open-solid.svg">
|
||||
135| <%= instance.folder %>
|
||||
|
||||
instance is not defined
|
||||
at eval ("./ejs/result.ejs":27:26)
|
||||
at result (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:703:17)
|
||||
at tryHandleCache (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:274:36)
|
||||
at exports.renderFile (D:\Documents\DCSOlympus\manager\node_modules\ejs\lib\ejs.js:491:10)
|
||||
at ResultPage.show (D:\Documents\DCSOlympus\manager\javascripts\result.js:25:13)
|
||||
at PasswordsPage.onNextClicked (D:\Documents\DCSOlympus\manager\javascripts\passwords.js:40:33)
|
||||
at HTMLDivElement.<anonymous> (D:\Documents\DCSOlympus\manager\javascripts\managerpage.js:39:87) {
|
||||
path: './ejs/result.ejs'
|
||||
}
|
||||
======================= New log starting at Fri Jan 12 2024 08:54:41 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
Instance C:\Users\dpassoni\Saved Games\dcs.openbeta client port set to 3000
|
||||
Instance C:\Users\dpassoni\Saved Games\dcs.openbeta client port set to 3001
|
||||
======================= New log starting at Fri Jan 12 2024 08:56:11 GMT+0100 (Central European Standard Time) =======================
|
||||
Running in D:\Documents\DCSOlympus\manager\javascripts
|
||||
Instance C:\Users\dpassoni\Saved Games\dcs.openbeta client port set to 3000
|
||||
Instance C:\Users\dpassoni\Saved Games\dcs.openbeta client port set to 3001
|
||||
Installing hooks in C:\Users\dpassoni\Saved Games\dcs.openbeta
|
||||
Error installing hooks in C:\Users\dpassoni\Saved Games\dcs.openbeta: Error: ENOENT: no such file or directory, lstat 'D:\Documents\DCSOlympus\scripts\OlympusHook.lua'
|
||||
@ -186,34 +186,6 @@ body {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.instructions {
|
||||
color: var(--offwhite);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 10px;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.instructions>span {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.instructions>span:first-child {
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.instructions>span:not(:first-child) {
|
||||
font-size: 15px;
|
||||
color: var(--gray);
|
||||
}
|
||||
|
||||
.buttons-footer {
|
||||
display: flex;
|
||||
column-gap: 10px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.button {
|
||||
padding: 10px 15px;
|
||||
border-radius: 5px;
|
||||
@ -225,23 +197,6 @@ body {
|
||||
column-gap: 10px;
|
||||
}
|
||||
|
||||
.next {
|
||||
color: var(--background);
|
||||
background-color: var(--offwhite);
|
||||
}
|
||||
|
||||
.back {
|
||||
color: var(--offwhite);
|
||||
background-color: var(--background);
|
||||
border: 1px solid var(--offwhite);
|
||||
}
|
||||
|
||||
.cancel {
|
||||
padding: 10px 5px;
|
||||
color: var(--offwhite);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.close-popup {
|
||||
color: var(--offwhite);
|
||||
background-color: var(--blue);
|
||||
@ -273,13 +228,13 @@ input {
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: black;
|
||||
opacity: 30%;
|
||||
background-color: white;
|
||||
opacity: 15%;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
#popup {
|
||||
width: 400px;
|
||||
width: 450px;
|
||||
height: fit-content;
|
||||
min-height: 200px;
|
||||
position: absolute;
|
||||
@ -290,7 +245,7 @@ input {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding: 20px;
|
||||
padding: 20px 40px;
|
||||
align-items: start;
|
||||
z-index: 999;
|
||||
}
|
||||
@ -311,6 +266,8 @@ input {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding: 15px 0px !important;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
#popup .footer {
|
||||
@ -326,87 +283,6 @@ input {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.manager-page>div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.step-summary {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
width: 30%;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--offwhite);
|
||||
border-left: 1px dashed var(--offwhite);
|
||||
height: 200px;
|
||||
row-gap: 100px;
|
||||
margin-left: 80px;
|
||||
}
|
||||
|
||||
.step-summary div {
|
||||
display: flex;
|
||||
width: 280px;
|
||||
height: 80px;
|
||||
align-items: center;
|
||||
column-gap: 15px;
|
||||
margin-left: -15px;
|
||||
margin-top: -40px;
|
||||
margin-bottom: -40px;
|
||||
font-size: 14px;
|
||||
color: var(--gray);
|
||||
}
|
||||
|
||||
.step-summary div:before {
|
||||
display: inline-block;
|
||||
content: "";
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border: 1px solid var(--offwhite);
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.step-summary div.white {
|
||||
color: var(--offwhite);
|
||||
}
|
||||
|
||||
.step-summary div.blue {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.step-summary div.white:before {
|
||||
background-color: var(--offwhite);
|
||||
}
|
||||
|
||||
.step-summary div.empty:before {
|
||||
background-color: var(--background);
|
||||
}
|
||||
|
||||
.step-summary div.blue:before {
|
||||
border: 1px solid var(--blue);
|
||||
background-color: var(--blue);
|
||||
}
|
||||
|
||||
.content {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 20px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.content>div {
|
||||
max-width: 60%;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
color: var(--offwhite);
|
||||
display: flex;
|
||||
@ -445,10 +321,6 @@ input {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.buttons-footer {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
border-top: 0px solid transparent !important;
|
||||
border-bottom: 1px solid var(--offwhite) !important;
|
||||
@ -482,6 +354,11 @@ input {
|
||||
background-position: 50% 50%;
|
||||
}
|
||||
|
||||
.button.collapse.loading::after {
|
||||
background-image: url("../icons/spinner-solid.svg");
|
||||
animation: rotate 2s linear infinite;
|
||||
}
|
||||
|
||||
.button.collapse>div {
|
||||
display: none;
|
||||
position: absolute;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user