Readded dashboard to manager

This commit is contained in:
Pax1601 2024-01-23 08:01:34 +01:00
parent 05f98b2738
commit 6f7b251094
15 changed files with 355 additions and 146 deletions

View File

@ -45,11 +45,10 @@
<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">
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"] %>">
<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>
@ -59,11 +58,10 @@
<div class="input-group backend-port">
<span>Backend port
<img src="./icons/circle-info-solid.svg"
title="This port is used by Olympus to communicate with DCS.
You only need to allow it through your firewall if you enable direct API connection">
title="This port is used by Olympus to communicate with DCS. You only need to allow it through your firewall if you enable direct API connection">
</span>
<div>
<input type="number" min="1024" max="65535" value="<%= activeInstance[" backendPort"] %>"
<input type="number" min="1024" max="65535" value="<%= activeInstance["backendPort"] %>"
onchange="signal('onBackendPortChanged', this.value)">
<img class="success hide">
<div class="error hide">
@ -75,12 +73,10 @@
<span onclick="signal('onEnableAPIClicked')">
<div class="checkbox"></div> Enable direct backend API connection
<img src="./icons/circle-info-solid.svg"
title="Allows services to connect to Olympus directly.
This is NOT NEEDED for normal Olympus operation, even for dedicated servers.
Leave it unchecked if in doubt.">
title="Allows services to connect to Olympus directly. This is NOT NEEDED for normal Olympus operation, even for dedicated servers. Leave it unchecked if in doubt.">
</span>
</div>
<div class="note warning">
<div class="note warning hide">
Note: if you enable direct backend API connection, you will be required to run DCS as admin or run the netsh
command for others to connect. Leave unchecked if you don't know what this is. <br>See the Olympus
documentation for more details.

View File

@ -1,9 +1,4 @@
<style>
#manager-instances {
padding-left: 80px;
padding-right: 80px;
}
#manager-instances .scroll-container {
height: 100%;
overflow-y: auto;
@ -18,7 +13,7 @@
height: fit-content;
width: 100%;
flex-wrap: wrap;
padding: 15px;
padding: 15px 40px;
}
#manager-instances .option {
@ -47,10 +42,6 @@
#manager-instances .option:not(.installed) .server-data {
opacity: 50%;
}
#manager-instances>.instructions {
margin-bottom: 10px;
}
#manager-instances .button.cancel {
position: absolute;
@ -119,7 +110,7 @@
#manager-instances .instance-info {
display: flex;
flex-direction: column;
row-gap: 5px;
row-gap: 10px;
width: 100%;
}
@ -225,13 +216,13 @@
}
</style>
<div id="manager-instances">
<div id="manager-instances" style="margin-bottom: 10px;">
<div class="content">
<div class="instructions">
<span>
<div class="instructions" style="display: flex; flex-direction: column; row-gap: 10px; align-items: center; padding: 20px;">
<span style="color: var(--offwhite); font-size: 18px; font-weight: 600;">
View and manage installs
</span>
<span>
<span style="color: var(--offwhite); font-size: 14px; text-align: center;">
The following DCS installations have been identified. <br>You can start an Olympus server, modify settings and uninstall below.
</span>
</div>
@ -241,10 +232,6 @@
<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': '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">
<div class="server-status webserver online hide">ACTIVE</div>
<div class="server-status webserver offline">OFFLINE</div>
@ -254,34 +241,42 @@
<div class="server-data-entry load"><img src="./icons/server-solid.svg"><span>Load: </span><span class="data">0</span></div>
<div class="server-data-entry uptime"></div>
</div>
<div class="divider"></div>
<div class="info">
<div>Client port</div>
<div> <%= instances[i].installed? instances[i].clientPort: "N/A" %> </div>
</div>
<div class="info">
<div>Backend port</div>
<div> <%= instances[i].installed? instances[i].backendPort: "N/A" %> </div>
</div>
<div class="info">
<div>Backend address</div>
<div> <%= instances[i].installed? instances[i].backendAddress: "N/A" %> </div>
<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 style="display: flex; flex-direction: column; row-gap: 5px;">
<div class="info">
<div>Client port</div>
<div> <%= instances[i].installed? instances[i].clientPort: "N/A" %> </div>
</div>
<div class="info">
<div>Backend port</div>
<div> <%= instances[i].installed? instances[i].backendPort: "N/A" %> </div>
</div>
<div class="info">
<div>Backend address</div>
<div> <%= instances[i].installed? instances[i].backendAddress: "N/A" %> </div>
</div>
</div>
</div>
<div class="instance-buttons">
<div class="button start collapse">
Start Olympus
<div>
<div class="button start-server">Start server</div>
<div class="button start-client">Start client</div>
<div class="button start-server" onclick="signal('onStartServerClicked', '<%= instances[i].name %>')">Start server</div>
<div class="button start-client" onclick="signal('onStartClientClicked', '<%= instances[i].name %>')">Start client</div>
</div>
</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>
<div class="button edit" onclick="signal('onEditClicked', '<%= instances[i].name %>')">Edit settings</div>
<div class="button install" onclick="signal('onInstallClicked', '<%= instances[i].name %>')">Install Olympus</div>
<div class="button uninstall" onclick="signal('onUninstallClicked', '<%= instances[i].name %>')">Uninstall Olympus</div>
<div class="button open-browser hide" onclick="signal('onOpenBrowserClicked', '<%= instances[i].name %>')">Open in browser</div>
<div class="button stop hide" onclick="signal('onStopClicked', '<%= instances[i].name %>')">Stop Olympus</div>
</div>
</div>
<% } %>

View File

@ -80,13 +80,13 @@
</div>
</div>
<div id="menu" style="row-gap: 20px; width: 60%;">
<div class="option <%= installEnabled? '': 'disabled' %>" onclick="signal('onInstallClicked')">
<div class="option <%= installEnabled? '': 'disabled' %>" onclick="signal('onInstallMenuClicked')">
Add Olympus
<div>
Add or update Olympus to a new DCS instance
</div>
</div>
<div class="option <%= editEnabled? '': 'disabled' %>" onclick="signal('onEditClicked')">
<div class="option <%= editEnabled? '': 'disabled' %>" onclick="signal('onEditMenuClicked')">
Change settings
<div>
Adjust port, address and password settings

View File

@ -19,19 +19,22 @@
<span>Game Master Password<img src="./icons/circle-info-solid.svg"
title="This password is used to access Olympus as Game Master with full privileges.">
</span>
<input type="password" minlength="8">
<input type="password" minlength="8" onchange="signal('onGameMasterPasswordChanged', this.value)" value="<%= activeInstance["installed"]? 'This is a long string so that users know this is not actually their password. Hi Tony!': '' %>">
</div>
<div class="input-group blue-commander">
<span>Blue Commander Password<img src="./icons/circle-info-solid.svg"
title="This password is used to access Olympus as blue coalition Commander.">
</span>
<input type="password" minlength="8">
<input type="password" minlength="8" onchange="signal('onBlueCommanderPasswordChanged', this.value)" value="<%= activeInstance["installed"]? 'This is a long string so that users know this is not actually their password. Hi Tony!': '' %>">
</div>
<div class="input-group red-commander">
<span>Red Commander Password<img src="./icons/circle-info-solid.svg"
title="This password is used to access Olympus as red coalition Commander.">
</span>
<input type="password" minlength="8">
<input type="password" minlength="8" onchange="signal('onRedCommanderPasswordChanged', this.value)" value="<%= activeInstance["installed"]? 'This is a long string so that users know this is not actually their password. Hi Tony!': '' %>">
</div>
<div class="<%= activeInstance["installed"]? '': 'hide' %>" style="color: var(--offwhite); font-size: 14px; color: var(--lightgray);">
Note: to keep the old passwords, click <b>Next</b> without editing any value.
</div>
</div>
</div>

View File

@ -4,7 +4,6 @@
flex-direction: column;
row-gap: 30px;
padding: 60px 120px;
color: var(--offwhite);
}
#result-page .result-summary {
@ -29,11 +28,6 @@
font-size: 13px;
}
#result-page .result-summary.wait{
color: var(--offwhite);
border: 1px solid var(--offwhite);
}
#result-page .result-summary.success{
color: var(--background-color);
background-color: var(--green);
@ -44,6 +38,13 @@
background-color: var(--red);
}
#result-page .instructions-group {
display: flex;
color: var(--offwhite);
flex-direction: column;
row-gap: 15px;
}
#result-page .usage-instructions {
background-color: var(--background-usage);
border-radius: 10px;
@ -75,47 +76,67 @@
}
</style>
<div id="result-page">
<div class="result-summary wait">
<div class="title"><img src="./icons/spinner-solid.svg" style="animation: rotate 2s linear infinite;">Please wait while Olympus is being added to <i><%= activeInstance["name"] %></i></div>
</div>
<div class="result-summary success hide">
<div class="title"><img src="./icons/check-solid-background.svg">Olympus successfully added to <i><%= activeInstance["name"] %></i></div>
<div class="title"><img src="./icons/check-solid-background.svg">Olympus successfully added to <i style="margin-left: 3px"><%= activeInstance["name"] %></i></div>
<div class="description">See the <b>DCS Olympus Wiki</b> for more information on how to use Olympus and for troubleshooting issues. You may now close the installer.</div>
</div>
<div class="result-summary error hide">
<div class="title"><img src="./icons/triangle-exclamation-solid-background.svg">An error occurred while adding Olympus to <i><%= activeInstance["name"] %></i></div>
<div class="description">See the manager log located in TODO for more information.</div>
</div>
<div style="font-size: 18px; font-weight: bold;">
How to launch Olympus
</div>
<div style="font-size: 13px;">
To launch Olympus, there are shortcuts available in the DCS Olympus folder under Saved Games.
</div>
<div class="usage-instructions">
<div>
<img src="./icons/server-solid.svg">
<div>
Launch the Olympus Server via the shortcut in DCS Olympus / Saved Games.
</div>
<div class="instructions-group hide">
<div style="font-size: 18px; font-weight: bold; color: var(--offwhite);">
How to launch Olympus
</div>
<img src="./icons/arrow-right-solid.svg">
<div>
<img src="./icons/chrome.svg">
<div>
Visit http://localhost:3000 in a web browser (Google Chrome recommended).
</div>
<div style="font-size: 13px; color: var(--offwhite);">
To launch Olympus, there are shortcuts available in the DCS Olympus folder under Saved Games.
</div>
<img src="./icons/arrow-right-solid.svg">
<div>
<img src="./icons/gamepad-solid.svg">
<div>
Launch DCS, load a mission and unpause the game. Enjoy!
<% if (activeInstance["installationType"] === "singleplayer") { %>
<div class="usage-instructions" style="width: 600px;">
<div>
<img src="./icons/olympus_white.png">
<div>
Launch the Olympus Client via the shortcut in DCS Olympus / Saved Games.
</div>
</div>
<img src="./icons/arrow-right-solid.svg">
<div>
<img src="./icons/gamepad-solid.svg">
<div>
Launch DCS, load a mission and unpause the game. Enjoy!
</div>
</div>
</div>
</div>
</div>
<div style="font-size: 13px;">
Alternatively, you can run the Olympus Client instead to replace the first two steps above.
<div style="font-size: 13px;">
Alternatively, you can run the Olympus Server instead and visit http://localhost:<%= activeInstance["clientPort"] %> in a web browser (Google Chrome recommended) to replace the first step above.
</div>
<% } else { %>
<div class="usage-instructions">
<div>
<img src="./icons/server-solid.svg">
<div>
Launch the Olympus Server via the shortcut in DCS Olympus / Saved Games.
</div>
</div>
<img src="./icons/arrow-right-solid.svg">
<div>
<img src="./icons/chrome.svg">
<div>
Visit http://<%= ip %>:<%= activeInstance["clientPort"] %> in a web browser (Google Chrome recommended).
</div>
</div>
<img src="./icons/arrow-right-solid.svg">
<div>
<img src="./icons/gamepad-solid.svg">
<div>
Launch DCS, load a mission and unpause the game. Enjoy!
</div>
</div>
</div>
<div style="font-size: 13px;">
Note, to access Olympus from this PC, you need to visit http://localhost:<%= activeInstance["clientPort"] %> in a web browser (Google Chrome recommended) instead.
</div>
<% } %>
</div>
<div class="buttons-footer">

View File

@ -70,8 +70,8 @@
}
</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 class="cancel" style="font-size: 14px; font-weight: 600; color: var(--offwhite); display: flex; align-items: center; column-gap: 10px; cursor: pointer; text-decoration: underline;" onclick="signal('onCancelClicked')">
<img src="./icons/chevron-left-solid.svg" style=" height: 14px;">Cancel install
</div>
<div class="content">

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -9,8 +9,9 @@ const dircompare = require('dir-compare');
const { spawn } = require('child_process');
const find = require('find-process');
const { uninstallInstance, installHooks, installMod, installJSON, applyConfiguration, installShortCuts } = require('./filesystem')
const { showErrorPopup, showConfirmPopup } = require('./popup')
const { showErrorPopup, showConfirmPopup, showWaitPopup } = require('./popup')
const { logger } = require("./filesystem")
const { hidePopup } = require('./popup')
class DCSInstance {
static instances = null;
@ -81,6 +82,9 @@ class DCSInstance {
fps = 0;
installationType = 'singleplayer';
connectionsType = 'auto';
gameMasterPasswordEdited = false;
blueCommanderPasswordEdited = false;
redCommanderPasswordEdited = false;
constructor(folder) {
this.folder = folder;
@ -127,7 +131,7 @@ class DCSInstance {
/* Periodically "ping" Olympus to check if either the client or the backend are active */
window.setInterval(async () => {
await this.getData();
getManager().instancesPage.update();
getManager().updateInstances();
}, 1000);
}
@ -167,6 +171,7 @@ class DCSInstance {
*/
setGameMasterPassword(newPassword) {
this.gameMasterPassword = newPassword;
this.gameMasterPasswordEdited = true;
}
/** Set Blue Commander password
@ -174,6 +179,7 @@ class DCSInstance {
*/
setBlueCommanderPassword(newPassword) {
this.blueCommanderPassword = newPassword;
this.blueCommanderPasswordEdited = true;
}
/** Set Red Commander password
@ -181,6 +187,19 @@ class DCSInstance {
*/
setRedCommanderPassword(newPassword) {
this.redCommanderPassword = newPassword;
this.redCommanderPasswordEdited = true;
}
arePasswordsEdited() {
return (getManager().getActiveInstance().gameMasterPasswordEdited || getManager().getActiveInstance().blueCommanderPasswordEdited || getManager().getActiveInstance().redCommanderPasswordEdited );
}
arePasswordsSet() {
return !(getManager().getActiveInstance().gameMasterPassword === '' || getManager().getActiveInstance().blueCommanderPassword === '' || getManager().getActiveInstance().redCommanderPassword === '');
}
arePasswordsDifferent() {
return !(getManager().getActiveInstance().gameMasterPassword === getManager().getActiveInstance().blueCommanderPassword || getManager().getActiveInstance().gameMasterPassword === getManager().getActiveInstance().redCommanderPassword || getManager().getActiveInstance().blueCommanderPassword === getManager().getActiveInstance().redCommanderPassword);
}
/** Check if the client port is free
@ -372,12 +391,15 @@ class DCSInstance {
}
).then(
() => {
getManager().resultPage.getElement().querySelector(".result-summary.wait").classList.add("hide");
hidePopup();
getManager().resultPage.show();
getManager().resultPage.getElement().querySelector(".result-summary.success").classList.remove("hide");
getManager().resultPage.getElement().querySelector(".result-summary.error").classList.add("hide");
getManager().resultPage.getElement().querySelector(".instructions-group").classList.remove("hide");
},
() => {
getManager().resultPage.getElement().querySelector(".result-summary.wait").classList.add("hide");
hidePopup();
getManager().resultPage.show();
getManager().resultPage.getElement().querySelector(".result-summary.success").classList.add("hide");
getManager().resultPage.getElement().querySelector(".result-summary.error").classList.remove("hide");
}
@ -386,7 +408,7 @@ class DCSInstance {
/* Uninstall this instance */
uninstall() {
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.", () =>
showConfirmPopup("<div style='font-size: 18px; max-width: 100%; margin-bottom: 15px;'> 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();

View File

@ -8,6 +8,8 @@ const { logger } = require("./filesystem")
const ManagerPage = require("./managerpage");
const WizardPage = require("./wizardpage");
const { fetchWithTimeout } = require("./net");
const { exec } = require("child_process");
class Manager {
options = {
@ -26,7 +28,6 @@ class Manager {
instancesPage = null;
constructor() {
console.log("constructor")
document.addEventListener("signal", (ev) => {
const callback = ev.detail.callback;
const params = JSON.stringify(ev.detail.params);
@ -74,6 +75,16 @@ class Manager {
/* Get the list of DCS instances */
this.options.instances = await DCSInstance.getInstances();
/* Get my public IP */
this.getPublicIP().then(
(ip) => {
this.options.ip = ip;
},
() => {
this.options.ip = undefined;
}
)
/* Check if there are corrupted or outdate instances */
if (this.options.instances.some((instance) => {
return instance.installed && instance.error;
@ -110,7 +121,7 @@ class Manager {
this.connectionsPage = new WizardPage(this, "./ejs/connections.ejs");
this.passwordsPage = new WizardPage(this, "./ejs/passwords.ejs");
this.resultPage = new ManagerPage(this, "./ejs/result.ejs");
//this.instancesPage = new InstancesPage(this);
this.instancesPage = new ManagerPage(this, "./ejs/instances.ejs");
if (this.options.mode === "basic") {
/* In basic mode no dashboard is shown */
@ -118,6 +129,7 @@ class Manager {
} else {
/* In Expert mode we go directly to the dashboard */
this.instancesPage.show();
this.updateInstances();
}
}
}
@ -157,7 +169,7 @@ class Manager {
}
/* When the install button is clicked go the installation page */
onInstallClicked() {
onInstallMenuClicked() {
this.options.install = true;
if (this.options.singleInstance) {
@ -168,7 +180,7 @@ class Manager {
this.menuPage.hide();
this.typePage.show();
} 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?",
showConfirmPopup("<div style='font-size: 18px; max-width: 100%; margin-bottom: 8px;'> 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();
@ -183,8 +195,8 @@ class Manager {
}
/* When the edit button is clicked go to the instances page */
onEditClicked() {
this.hide();
onEditMenuClicked() {
this.instancesPage.hide();
this.options.install = false;
if (this.options.singleInstance) {
@ -215,25 +227,20 @@ class Manager {
showErrorPopup("A critical error has occurred. Please restart the Manager.")
}
/* When the back button of a wizard page is clicked */
onBackClicked() {
this.activePage.hide();
this.activePage.previousPage.show();
}
/* When the next button of a wizard page is clicked */
onNextClicked() {
this.activePage.hide();
/* Choose which page to show depending on the active page */
if (this.activePage == this.typePage) {
this.activePage.hide();
this.connectionsTypePage.show();
} else if (this.activePage == this.connectionsTypePage) {
if (this.options.activeInstance) {
if (this.options.activeInstance.connectionsType === 'auto') {
this.activePage.hide();
this.passwordsPage.show();
}
else {
this.activePage.hide();
this.connectionsPage.show();
this.setPort('client', this.options.activeInstance.clientPort);
this.setPort('backend', this.options.activeInstance.backendPort);
@ -243,17 +250,79 @@ class Manager {
showErrorPopup("A critical error has occurred. Please restart the Manager.")
}
} else if (this.activePage == this.connectionsPage) {
this.activePage.hide();
this.passwordsPage.show();
} else if (this.activePage == this.passwordsPage) {
if (this.options.activeInstance) {
this.options.activeInstance.install();
this.resultPage.show();
if (this.options.activeInstance.installed && !this.options.activeInstance.arePasswordsEdited()) {
this.activePage.hide();
this.options.activeInstance.install();
showWaitPopup(`<span>Please wait while Olympus is being installed in <i>${this.options.activeInstance.name}</i></span>`);
}
else {
if (!this.options.activeInstance.arePasswordsSet()) {
showErrorPopup('Please, make sure all passwords are set!');
} else if (!this.options.activeInstance.arePasswordsDifferent()) {
showErrorPopup('Please, set different passwords for the Game Master, Blue Commander, and Red Commander roles!');
} else {
this.activePage.hide();
this.options.activeInstance.install();
showWaitPopup(`<span>Please wait while Olympus is being installed in <i>${this.options.activeInstance.name}</i></span>`);
}
}
} else {
showErrorPopup("A critical error has occurred. Please restart the Manager.")
}
}
}
/* When the back button of a wizard page is clicked */
onBackClicked() {
this.activePage.hide();
this.activePage.previousPage.show(true); // Don't change the previous page
this.updateInstances();
}
onCancelClicked() {
location.reload();
}
onGameMasterPasswordChanged(value) {
if (this.options.activeInstance) {
this.options.activeInstance.setGameMasterPassword(value);
if (!this.options.activeInstance.blueCommanderPasswordEdited)
this.passwordsPage.getElement().querySelector(".blue-commander input").value = "";
if (!this.options.activeInstance.redCommanderPasswordEdited)
this.passwordsPage.getElement().querySelector(".red-commander input").value = "";
}
else
showErrorPopup("A critical error has occurred. Please restart the Manager.")
}
onBlueCommanderPasswordChanged(value) {
if (this.options.activeInstance) {
this.options.activeInstance.setBlueCommanderPassword(value);
if (!this.options.activeInstance.gameMasterPasswordEdited)
this.passwordsPage.getElement().querySelector(".game-master input").value = "";
if (!this.options.activeInstance.redCommanderPasswordEdited)
this.passwordsPage.getElement().querySelector(".red-commander input").value = "";
}
else
showErrorPopup("A critical error has occurred. Please restart the Manager.")
}
onRedCommanderPasswordChanged(value) {
if (this.options.activeInstance) {
this.options.activeInstance.setRedCommanderPassword(value);
if (!this.options.activeInstance.gameMasterPasswordEdited)
this.passwordsPage.getElement().querySelector(".game-master input").value = "";
if (!this.options.activeInstance.blueCommanderPasswordEdited)
this.passwordsPage.getElement().querySelector(".blue-commander input").value = "";
}
else
showErrorPopup("A critical error has occurred. Please restart the Manager.")
}
/* When the client port input value is changed */
onClientPortChanged(value) {
this.setPort('client', Number(value));
@ -272,12 +341,91 @@ class Manager {
} else {
this.options.activeInstance.backendAddress = 'localhost';
}
this.connectionsPage.getElement().querySelector(".note.warning").classList.toggle("hide", this.options.activeInstance.backendAddress !== '*')
this.connectionsPage.getElement().querySelector(".backend-address .checkbox").classList.toggle("checked", this.options.activeInstance.backendAddress === '*')
} else {
showErrorPopup("A critical error has occurred. Please restart the Manager.")
}
}
/* When the "Return to manager" button is pressed */
onReturnClicked() {
location.reload();
}
/* When the "Close manager" button is pressed */
onCloseManagerClicked() {
document.querySelector('.close').click();
}
async onStartServerClicked(name) {
this.getClickedInstanceDiv(name).then((div) => div.querySelector(".collapse").classList.add("loading"));
this.getClickedInstance(name).then((instance) => instance.startServer());
}
async onStartClientClicked(name) {
this.getClickedInstanceDiv(name).then((div) => div.querySelector(".collapse").classList.add("loading"));
this.getClickedInstance(name).then(instance => instance.startClient());
}
async onOpenBrowserClicked(name) {
this.getClickedInstance(name).then((instance) => exec(`start http://localhost:${instance.clientPort}`));
}
async onStopClicked(name) {
this.getClickedInstance(name).then((instance) => instance.stop());
}
async onEditClicked(name) {
this.getClickedInstance(name).then((instance) => {
if (instance.webserverOnline || instance.backendOnline) {
showErrorPopup("Error, the selected Olympus instance is currently active, please stop Olympus before editing it!")
} else {
this.options.activeInstance = instance;
this.instancesPage.hide();
this.typePage.show();
}
});
}
async onInstallClicked(name) {
this.getClickedInstance(name).then((instance) => {
this.options.activeInstance = instance;
this.options.install = true;
this.options.singleInstance = false;
this.instancesPage.hide();
this.typePage.show();
});
}
async onUninstallClicked(name) {
this.getClickedInstance(name).then((instance) => {
instance.webserverOnline || instance.backendOnline ? showErrorPopup("Error, the selected Olympus instance is currently active, please stop Olympus before uninstalling it!") : instance.uninstall();
});
}
async getClickedInstance(name) {
return DCSInstance.getInstances().then((instances) => {
return instances.find((instance) => {
return instance.name === name
})
});
}
async getClickedInstanceDiv(name) {
var instance = await this.getClickedInstance(name);
console.log(instance)
var instanceDivs = this.instancesPage.getElement().querySelectorAll(`.option`);
for (let i = 0; i < instanceDivs.length; i++) {
var instanceDiv = instanceDivs[i];
console.log(instanceDiv.dataset.folder)
if (instanceDiv.dataset.folder === instance.folder) {
console.log(instanceDiv)
return instanceDiv;
}
}
}
/* Set the selected port to the dcs instance */
async setPort(port, value) {
var success;
@ -295,6 +443,49 @@ class Manager {
errorEls[i].classList.toggle("hide", success);
}
}
async getPublicIP() {
const res = await fetchWithTimeout("https://ipecho.io/json", { timeout: 2500 });
const data = await res.json();
return data.ip;
}
updateInstances() {
var instanceDivs = this.instancesPage.getElement().querySelectorAll(`.option`);
for (let i = 0; i < instanceDivs.length; i++) {
var instanceDiv = instanceDivs[i];
var instance = this.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);
if (instance.installed) {
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");
}
}
}
}
}
}
module.exports = Manager;

View File

@ -20,7 +20,7 @@ class ManagerPage {
return this.element;
}
show(previousPage) {
show(ignorePreviousPage) {
ejs.renderFile(this.ejsFile, {...this.options, ...this.manager.options}, {}, (err, str) => {
if (!err) {
this.render(str);
@ -31,7 +31,7 @@ class ManagerPage {
this.element.classList.remove("hide");
this.previousPage = this.manager.activePage;
this.previousPage = ignorePreviousPage ? this.previousPage : this.manager.activePage;
this.manager.activePage = this;
}

View File

@ -9,7 +9,7 @@ const fs = require('fs');
const AdmZip = require("adm-zip");
const { Octokit } = require('octokit');
const { logger } = require("./filesystem");
const { getManager } = require('./managerFactory');
const { getManager } = require('./managerfactory');
const VERSION = "{{OLYMPUS_VERSION_NUMBER}}";
logger.log(`Running in ${__dirname}`);

View File

@ -12,16 +12,6 @@ class WizardPage extends ManagerPage {
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;
@ -31,23 +21,6 @@ class WizardPage extends ManagerPage {
});
}
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;

View File

@ -48,7 +48,7 @@ class installationPage extends ManagerPage {
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?",
showConfirmPopup("<div style='font-size: 18px; max-width: 100%; margin-bottom: 15px;'> 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);

View File

@ -5,7 +5,7 @@
"main": "main.js",
"scripts": {
"start": "electron .",
"build-release": "call ./scripts/build-release.bat"
"build-release": "call ./scripts/build-release.bat"
},
"author": "",
"license": "ISC",
@ -26,4 +26,4 @@
"devDependencies": {
"nodemon": "^3.0.2"
}
}
}

View File

@ -145,7 +145,7 @@ body {
#loader {
color: var(--offwhite);
font-size: 20px;
font-size: 16px;
font-weight: normal;
position: absolute;
display: flex;
@ -206,6 +206,11 @@ body {
color: var(--offwhite);
}
.button.radio.selected {
background-color: var(--offwhite);
color: var(--background);
}
.button.radio::before {
content: "";
display: block;
@ -217,6 +222,9 @@ body {
.button.radio.selected::before {
background-color: var(--offwhite);
border: 4px solid var(--background);
width: 4px;
height: 4px;
}
.close-popup {