You can start an Olympus server, modify settings and uninstall below. + The following DCS installations have been identified.
You can start an Olympus server, modify settings and uninstall below.
+ If you want Olympus to be used on a different computer or over the internet for a dedicated server, select the multiplayer option. + +
+ Advanced mode is for those who know how Olympus works or for server owners. + + + You can change this setting at any time. + +
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 + 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 advanced mode */ + this.welcomePage = new WelcomePage(this); + document.body.appendChild(this.welcomePage.getElement()); + this.welcomePage.show(); + } + else { + document.getElementById("header").classList.remove("hide"); + + if (this.options.mode === "basic") { + document.getElementById("switch-mode").innerText = "Advanced mode"; + document.getElementById("switch-mode").onclick = () => { this.switchMode("advanced"); } } - 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("
If you have just updated Olympus this is normal.
Press Accept and the Manager will fix your instances for you.
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.
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 MenuPage(this); + this.installationsPage = new InstallationsPage(this); + this.typePage = new TypePage(this); + this.connectionsPage = new ConnectionsPage(this); + this.passwordsPage = new PasswordsPage(this); + this.resultPage = new ResultPage(this); + this.instancesPage = new InstancesPage(this); + + document.body.appendChild(this.menuPage.getElement()); + document.body.appendChild(this.installationsPage.getElement()); + document.body.appendChild(this.typePage.getElement()); + document.body.appendChild(this.connectionsPage.getElement()); + document.body.appendChild(this.passwordsPage.getElement()); + document.body.appendChild(this.resultPage.getElement()); + document.body.appendChild(this.instancesPage.getElement()); + + 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.
You can find more info in ${path.join(__dirname, "..", "manager.log")}`) + /* In advanced 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.
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.
You can find more info in ${path.join(__dirname, "..", "manager.log")}`) - } + getActiveInstance() { + return this.options.activeInstance; + } - } - 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(); - } + switchMode(newMode) { + var options = JSON.parse(fs.readFileSync("options.json")); + options.mode = newMode; + fs.writeFileSync("options.json", JSON.stringify(options)); + location.reload(); } } diff --git a/manager/javascripts/managerfactory.js b/manager/javascripts/managerfactory.js new file mode 100644 index 00000000..ef5165c5 --- /dev/null +++ b/manager/javascripts/managerfactory.js @@ -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 +}; \ No newline at end of file diff --git a/manager/javascripts/managerpage.js b/manager/javascripts/managerpage.js index 4a02a731..d1d9b8e8 100644 --- a/manager/javascripts/managerpage.js +++ b/manager/javascripts/managerpage.js @@ -1,8 +1,11 @@ class ManagerPage { + manager; element; options; + previousPage; - constructor(options) { + constructor(manager, options) { + this.manager = manager; this.options = options ?? {}; this.element = document.createElement('div'); this.element.classList.add("manager-page", "hide"); @@ -12,8 +15,11 @@ class ManagerPage { return this.element; } - show() { + show(previousPage) { this.element.classList.remove("hide"); + + if (previousPage !== undefined) + this.previousPage = previousPage; } hide() { @@ -28,6 +34,21 @@ class ManagerPage { buttons[i].classList.toggle("open"); }) } + + /* 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)); + } + + onBackClicked() { + this.hide(); + this.previousPage.show() } } diff --git a/manager/javascripts/menu.js b/manager/javascripts/menu.js index 57657263..3a475818 100644 --- a/manager/javascripts/menu.js +++ b/manager/javascripts/menu.js @@ -1,14 +1,11 @@ const ManagerPage = require("./managerpage"); const ejs = require('ejs') -const { logger } = require("./filesystem") +const { logger } = require("./filesystem"); +const { showConfirmPopup } = require("./popup"); class MenuPage extends ManagerPage { - onInstallClicked; - onUpdateClicked; - onManageClicked; - - constructor(options) { - super(options); + constructor(manager, options) { + super(manager, options); } render(str) { @@ -16,15 +13,14 @@ class MenuPage extends ManagerPage { element.innerHTML = str; element.querySelector(".install").addEventListener("click", (e) => this.onInstallClicked(e)); - element.querySelector(".manage").addEventListener("click", (e) => this.onManageClicked(e)); + element.querySelector(".edit").addEventListener("click", (e) => this.onEditClicked(e)); + element.querySelector(".uninstall").addEventListener("click", (e) => this.onUninstallClicked(e)); super.render(); } - show() { - this.instance = this.options.instance; - - ejs.renderFile("./ejs/menu.ejs", this.options, {}, (err, str) => { + show(previousPage) { + ejs.renderFile("./ejs/menu.ejs", {...this.options, ...this.manager.options}, {}, (err, str) => { if (!err) { this.render(str); } else { @@ -32,8 +28,60 @@ class MenuPage extends ManagerPage { } }); - super.show(); + super.show(previousPage); } + + /* When the install button is clicked go the installation page */ + onInstallClicked(e) { + this.manager.options.install = true; + + if (this.manager.options.singleInstance) { + this.manager.options.activeInstance = this.manager.options.instances[0]; + + /* Show the connections page */ + if (!this.manager.options.activeInstance.installed) { + this.hide(); + this.manager.typePage.show(this); + } else { + showConfirmPopup("