diff --git a/manager/ejs/installations.ejs b/manager/ejs/installations.ejs index efff26b1..550dbc10 100644 --- a/manager/ejs/installations.ejs +++ b/manager/ejs/installations.ejs @@ -32,6 +32,7 @@ } #manager-installations .option { + position: relative; display: flex; flex-direction: column; row-gap: 5px; @@ -70,6 +71,19 @@ #manager-installations .option.installed { pointer-events: none; + background-color: var(--background-disabled); + } + + #manager-installations .option:not(.installed)::after { + display: block; + content: " "; + width: 20px; + height: 20px; + background-image: url("./icons/chevron-right-solid.svg"); + background-repeat: no-repeat; + background-position: 50% 50%; + position: absolute; + right: 20px; }
@@ -98,7 +112,7 @@ <%= instances[i].name %> <%= instances[i].folder %> - <%= instances[i].installed? (instances[i].error? 'Corrupted/outdated Olympus installation': 'Olympus already installed'): 'Olympus not installed yet' %> + <%= instances[i].installed? (instances[i].error? 'Corrupted/outdated Olympus installation': 'Olympus installed'): 'Olympus not installed' %>
<% } %> diff --git a/manager/ejs/instances.ejs b/manager/ejs/instances.ejs index 0f81c636..e059c725 100644 --- a/manager/ejs/instances.ejs +++ b/manager/ejs/instances.ejs @@ -43,7 +43,7 @@ #manager-instances .button.cancel { position: absolute; left: 110px; - top: 180px; + top: 130px; } #manager-instances .server-data { @@ -104,25 +104,120 @@ font-weight: normal; } - #manager-instances .start-stop-client { - margin-right: auto; + #manager-instances .instance-info { + display: flex; + flex-direction: column; + row-gap: 5px; + width: 100%; } + #manager-instances .instance-info>span:nth-child(1) { + font-size: 18px; + font-weight: 600; + } + + #manager-instances .instance-info>span:nth-child(2) { + font-size: 13px; + font-weight: 600; + color: var(--lightgray); + } + + #manager-instances .instance-info>span:nth-child(2).installed { + font-weight: 600; + color: var(--green); + } + + #manager-instances .instance-info>span:nth-child(2).error { + font-weight: 600; + color: orange; + } + + #manager-instances .instance-info>span:nth-child(3) { + font-size: 13px; + font-weight: normal; + color: var(--lightgray); + display: flex; + align-items: center; + column-gap: 8px; + } + + #manager-instances .instance-info>span:nth-child(4) { + display: flex; + column-gap: 10px; + font-size: 13px; + font-weight: normal; + } + + #manager-instances .instance-buttons { + display: flex; + flex-direction: row; + width: 100%; + justify-content: space-between; + column-gap: 10px; + } + + #manager-instances .instance-info .info { + display: flex; + flex-direction: row; + justify-content: space-between; + } + + #manager-instances .instance-info .info>div:nth-child(1) { + font-weight: 600; + font-size: 14px; + } + + #manager-instances .instance-info .info>div:nth-child(2) { + font-weight: normal; + font-size: 14px; + } + + #manager-instances .instance-info .divider { + margin-top: 5px; + margin-bottom: 5px; + } + + #manager-instances .start, #manager-instances .open-browser { + margin-right: auto; + color: var(--offwhite); + background-color: var(--blue); + } + + #manager-instances .start { + width: 160px; + } + + #manager-instances .start>div { + width: 160px; + } + + #manager-instances .edit, + #manager-instances .uninstall, + #manager-instances .stop { + color: var(--offwhite); + background-color: transparent; + border: 1px solid var(--offwhite); + } + + #manager-instances .edit:hover, + #manager-instances .uninstall:hover, + #manager-instances .stop:hover { + color: var(--background); + background-color: var(--offwhite); + } +
- Return to menu + Return to menu
- <%= manage? "View and manage instances": "Update Olympus settings" %> + View and manage installs - The following versions of Olympus have been detected. - - - <%= manage? "You can inspect and manage you Olympus instances by selecting the options below.": "You can edit your settings or remove Olympus by selecting the options below." %> + The following Oympus installs have been identified.
You can start an Olympus server, modify settings and uninstall below.
@@ -134,19 +229,16 @@ <%= instances[i].installed? (instances[i].error? 'Corrupted/outdated Olympus installation': ''): '' %> - <% if (!manage) { %> - <%= instances[i].folder %> - <% } else { %> -
-
ACTIVE
-
OFFLINE
-
CONNECTED
-
DISCONNECTED
-
FPS: 0
-
Load: 0
-
-
- <% } %> + <%= instances[i].folder %> +
+
ACTIVE
+
OFFLINE
+
CONNECTED
+
DISCONNECTED
+
FPS: 0
+
Load: 0
+
+
Client port
@@ -162,13 +254,18 @@
- <% if (!manage) { %> -
Edit settings
-
Uninstall
- <% } else { %> -
Start server
-
Start client
- <% } %> +
+ Start Olympus +
+
Start server
+
Start client
+
+
+ +
Edit settings
+
Uninstall Olympus
+
Open in browser
+
Stop Olympus
<% } %> diff --git a/manager/ejs/menu.ejs b/manager/ejs/menu.ejs index c366bee0..412c0b15 100644 --- a/manager/ejs/menu.ejs +++ b/manager/ejs/menu.ejs @@ -85,12 +85,8 @@
Install Olympus
-
- Update/remove Olympus -
-
- View and manage instances + View / Manage installs
\ No newline at end of file diff --git a/manager/icons/chevron-down-solid.svg b/manager/icons/chevron-down-solid.svg new file mode 100644 index 00000000..46aeebb0 --- /dev/null +++ b/manager/icons/chevron-down-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/manager/icons/chevron-left-solid.svg b/manager/icons/chevron-left-solid.svg new file mode 100644 index 00000000..288a94f7 --- /dev/null +++ b/manager/icons/chevron-left-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/manager/icons/chevron-right-solid.svg b/manager/icons/chevron-right-solid.svg new file mode 100644 index 00000000..c0b6539c --- /dev/null +++ b/manager/icons/chevron-right-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/manager/icons/discord.svg b/manager/icons/discord.svg new file mode 100644 index 00000000..00c6254a --- /dev/null +++ b/manager/icons/discord.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/manager/icons/github.svg b/manager/icons/github.svg new file mode 100644 index 00000000..013cde4f --- /dev/null +++ b/manager/icons/github.svg @@ -0,0 +1,3 @@ + + + diff --git a/manager/icons/youtube.svg b/manager/icons/youtube.svg new file mode 100644 index 00000000..c8718c4c --- /dev/null +++ b/manager/icons/youtube.svg @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/manager/index.html b/manager/index.html index 96ed27cb..f89cfbab 100644 --- a/manager/index.html +++ b/manager/index.html @@ -26,8 +26,12 @@
DCS Olympus Manager
{{OLYMPUS_VERSION_NUMBER}}
- - + + +
+ + +
Loading, please wait... diff --git a/manager/javascripts/connections.js b/manager/javascripts/connections.js index 9383f6ab..7d01f2e1 100644 --- a/manager/javascripts/connections.js +++ b/manager/javascripts/connections.js @@ -31,6 +31,8 @@ class ConnectionsPage extends ManagerPage { 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); }) + + super.render(); } show() { diff --git a/manager/javascripts/dcsinstance.js b/manager/javascripts/dcsinstance.js index 0a8842ab..715be367 100644 --- a/manager/javascripts/dcsinstance.js +++ b/manager/javascripts/dcsinstance.js @@ -139,11 +139,17 @@ class DCSInstance { if (this.backendOnline) { instanceDiv.querySelector(".fps .data").innerText = this.fps; - instanceDiv.querySelector(".load .data").innerTexr = this.load; + instanceDiv.querySelector(".load .data").innerText = this.load; } - instanceDiv.querySelector(".start-stop-server").innerText = this.webserverOnline ? "Stop" : "Start server"; - instanceDiv.querySelector(".start-stop-client").innerText = this.webserverOnline ? "Open in browser" : "Start client"; + 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) + + if (this.webserverOnline) + instanceDiv.querySelector(".button.start").classList.remove("loading") } } } @@ -354,7 +360,6 @@ class DCSInstance { } } else { - logger.log(list[0]) logger.error(`The process listening on the specified port has an incorrect name: ${list[0].name}`) } } diff --git a/manager/javascripts/installations.js b/manager/javascripts/installations.js index 2cab3b9e..c3014acb 100644 --- a/manager/javascripts/installations.js +++ b/manager/javascripts/installations.js @@ -20,6 +20,8 @@ class InstallationsPage extends ManagerPage { } this.element.querySelector(".cancel").addEventListener("click", (e) => this.onCancelClicked(e)); + + super.render(); } async onOptionClicked(e) { diff --git a/manager/javascripts/instances.js b/manager/javascripts/instances.js index f93e576e..aa149fe8 100644 --- a/manager/javascripts/instances.js +++ b/manager/javascripts/instances.js @@ -17,47 +17,79 @@ class InstancesPage extends ManagerPage { render(str) { this.element.innerHTML = str; - var editButtons = this.element.querySelectorAll(".edit"); + var editButtons = this.element.querySelectorAll(".button.edit"); for (let i = 0; i < editButtons.length; i++) { editButtons[i].onclick = (e) => {this.onEditClicked(e);} } - var uninstallButtons = this.element.querySelectorAll(".uninstall"); + var uninstallButtons = this.element.querySelectorAll(".button.uninstall"); for (let i = 0; i < uninstallButtons.length; i++) { uninstallButtons[i].onclick = (e) => {this.onUninstallClicked(e);} } - var startStopServerButtons = this.element.querySelectorAll(".start-stop-server"); - for (let i = 0; i < startStopServerButtons.length; i++) { - startStopServerButtons[i].onclick = (e) => {this.onStartStopServerClicked(e);} + var startServerButtons = this.element.querySelectorAll(".button.start-server"); + for (let i = 0; i < startServerButtons.length; i++) { + startServerButtons[i].onclick = (e) => {this.onStartServerClicked(e);} } - var startStopClientButtons = this.element.querySelectorAll(".start-stop-client"); - for (let i = 0; i < startStopClientButtons.length; i++) { - startStopClientButtons[i].onclick = (e) => {this.onStartStopClientClicked(e);} + var startClientButtons = this.element.querySelectorAll(".button.start-client"); + for (let i = 0; i < startClientButtons.length; i++) { + startClientButtons[i].onclick = (e) => {this.onStartClientClicked(e);} + } + + var openBrowserButtons = this.element.querySelectorAll(".button.open-browser"); + for (let i = 0; i < openBrowserButtons.length; i++) { + openBrowserButtons[i].onclick = (e) => {this.onOpenBrowserClicked(e);} + } + + var stopButtons = this.element.querySelectorAll(".button.stop"); + for (let i = 0; i < stopButtons.length; i++) { + stopButtons[i].onclick = (e) => {this.onStopClicked(e);} } this.element.querySelector(".cancel").addEventListener("click", (e) => this.onCancelClicked(e)); + + super.render(); } async onEditClicked(e) { - logger.log(e.target.dataset.folder) - this.setSelectedInstance((await DCSInstance.getInstances()).find((instance) => {return instance.folder === e.target.closest('.option').dataset.folder})); + 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 onStartStopServerClicked(e) { - var instance = (await DCSInstance.getInstances()).find((instance) => {return instance.folder === e.target.closest('.option').dataset.folder}); - instance.webserverOnline? instance.stop(): instance.startServer(); + async onStartServerClicked(e) { + e.target.closest(".collapse").classList.add("loading"); + this.getClickedInstance(e).then((instance) => instance.startServer()); } - async onStartStopClientClicked(e) { - var instance = (await DCSInstance.getInstances()).find((instance) => {return instance.folder === e.target.closest('.option').dataset.folder}); - instance.webserverOnline? exec(`start http://localhost:${instance.clientPort}`): instance.startClient(); + async onStartClientClicked(e) { + e.target.closest(".collapse").classList.add("loading"); + this.getClickedInstance(e).then(instance => instance.startClient()); + } + + async onOpenBrowserClicked(e) { + this.getClickedInstance(e).then((instance) => exec(`start http://localhost:${instance.clientPort}`)); + } + + async onStopClicked(e) { + this.getClickedInstance(e).then((instance) => instance.stop()); } async onUninstallClicked(e) { - var instance = (await DCSInstance.getInstances()).find((instance) => {return instance.folder === e.target.closest('.option').dataset.folder}); - instance.webserverOnline || instance.backendOnline? showErrorPopup("Error, the selected Olympus instance is currently active, please stop Olympus before uninstalling it!") : instance.uninstall(); + 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(); + }); + } + + async getClickedInstance(e) { + return DCSInstance.getInstances().then((instances) => { + return instances.find((instance) => { + return instance.folder === e.target.closest('.option').dataset.folder + }) + }); } show() { diff --git a/manager/javascripts/manager.js b/manager/javascripts/manager.js index 77d2ad60..fcccc21b 100644 --- a/manager/javascripts/manager.js +++ b/manager/javascripts/manager.js @@ -47,8 +47,7 @@ class Manager { } /* Check which buttons should be enabled */ - const installEnabled = instances.some((instance) => { return !instance.installed; }); - const updateEnabled = instances.some((instance) => { return instance.installed; }); + const installEnabled = true; const manageEnabled = instances.some((instance) => { return instance.installed; }); /* Menu */ @@ -56,7 +55,6 @@ class Manager { menuPage.options = { ...menuPage.options, installEnabled: installEnabled, - updateEnabled: updateEnabled, manageEnabled: manageEnabled } /* When the install button is clicked go the installation page */ @@ -64,22 +62,9 @@ class Manager { menuPage.hide(); installationsPage.show(); } - /* When the update button is clicked go to the instances page in "update mode" (i.e. manage = false) */ - menuPage.onUpdateClicked = (e) => { - menuPage.hide(); - instancesPage.options = { - ...instancesPage.options, - manage: false - } - instancesPage.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.options = { - ...instancesPage.options, - manage: true - } instancesPage.show(); } diff --git a/manager/javascripts/managerpage.js b/manager/javascripts/managerpage.js index 471e427b..4a02a731 100644 --- a/manager/javascripts/managerpage.js +++ b/manager/javascripts/managerpage.js @@ -19,6 +19,16 @@ class ManagerPage { hide() { this.element.classList.add("hide"); } + + render() { + /* 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"); + }) + } + } } module.exports = ManagerPage; \ No newline at end of file diff --git a/manager/javascripts/menu.js b/manager/javascripts/menu.js index 1b534c10..57657263 100644 --- a/manager/javascripts/menu.js +++ b/manager/javascripts/menu.js @@ -16,8 +16,9 @@ class MenuPage extends ManagerPage { element.innerHTML = str; element.querySelector(".install").addEventListener("click", (e) => this.onInstallClicked(e)); - element.querySelector(".update").addEventListener("click", (e) => this.onUpdateClicked(e)) - element.querySelector(".manage").addEventListener("click", (e) => this.onManageClicked(e)) + element.querySelector(".manage").addEventListener("click", (e) => this.onManageClicked(e)); + + super.render(); } show() { diff --git a/manager/javascripts/passwords.js b/manager/javascripts/passwords.js index fda5ca6d..fe9ed99a 100644 --- a/manager/javascripts/passwords.js +++ b/manager/javascripts/passwords.js @@ -27,6 +27,8 @@ class PasswordsPage extends ManagerPage { 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); }) + + super.render(); } show() { diff --git a/manager/javascripts/result.js b/manager/javascripts/result.js index f58ab34c..d55bb1b1 100644 --- a/manager/javascripts/result.js +++ b/manager/javascripts/result.js @@ -17,6 +17,8 @@ class ResultPage extends ManagerPage { element.innerHTML = str; this.element.querySelector(".back").addEventListener("click", (e) => this.onBackClicked(e)); + + super.render(); } show() { diff --git a/manager/scripts/mirror-package.bat b/manager/scripts/mirror-package.bat index 92c3ea44..7b2055b1 100644 --- a/manager/scripts/mirror-package.bat +++ b/manager/scripts/mirror-package.bat @@ -1 +1 @@ -nodemon --watch . --exec "./scripts/copy-package" \ No newline at end of file +nodemon --watch ./**/*.* --exec "./scripts/copy-package" \ No newline at end of file diff --git a/manager/stylesheets/style.css b/manager/stylesheets/style.css index 525f8fa8..b83e9deb 100644 --- a/manager/stylesheets/style.css +++ b/manager/stylesheets/style.css @@ -1,7 +1,10 @@ :root { --background: #181e25; --background-dark: #13181f; + --background-light: #202831; + --background-disabled: #212A34; --offwhite: #F2F2F2; + --offwhite-transparent: #F2F2F255; --blue: #247be2; --red: #FF5858; --green: #8bff63; @@ -85,7 +88,7 @@ body { #header { display: flex; justify-content: start; - align-items: start; + align-items: center; color: #F2F2F2; font-weight: bold; font-size: 16px; @@ -109,6 +112,10 @@ body { height: 60px; } +#header img.link { + height: 20px; +} + .link { font-weight: normal; text-decoration: underline; @@ -213,6 +220,9 @@ body { font-size: 13px; font-weight: 600; cursor: pointer; + display: flex; + align-items: center; + column-gap: 10px; } .next { @@ -220,17 +230,6 @@ body { background-color: var(--offwhite); } -.uninstall { - color: var(--offwhite); - background-color: transparent; - border: 1px solid var(--offwhite); -} - -.edit, .start-stop-server, .start-stop-client { - color: var(--offwhite); - background-color: var(--blue); -} - .back { color: var(--offwhite); background-color: var(--background); @@ -312,6 +311,8 @@ input { width: 100%; text-align: left; padding: 15px 0px !important; + word-wrap: break-word; + overflow-wrap: anywhere; } #popup .footer { @@ -450,65 +451,6 @@ input { margin-top: 10px; } -.instance-info { - display: flex; - flex-direction: column; - row-gap: 5px; - width: 100%; -} - -.instance-info>span:nth-child(1) { - font-size: 18px; - font-weight: 600; -} - -.instance-info>span:nth-child(2) { - font-size: 13px; - font-weight: 600; - color: var(--lightgray); -} - -.instance-info>span:nth-child(2).installed { - font-weight: 600; - color: var(--green); -} - -.instance-info>span:nth-child(2).error { - font-weight: 600; - color: orange; -} - -.instance-info>span:nth-child(3) { - display: flex; - column-gap: 10px; - font-size: 13px; - font-weight: normal; -} - -.instance-buttons { - display: flex; - flex-direction: row; - width: 100%; - justify-content: space-between; - column-gap: 10px; -} - -.instance-info .info { - display: flex; - flex-direction: row; - justify-content: space-between; -} - -.instance-info .info>div:nth-child(1) { - font-weight: 600; - font-size: 14px; -} - -.instance-info .info>div:nth-child(2) { - font-weight: normal; - font-size: 14px; -} - .divider { border-top: 0px solid transparent !important; border-bottom: 1px solid var(--offwhite) !important; @@ -517,11 +459,6 @@ input { cursor: default; } -.instance-info .divider { - margin-top: 15px; - margin-bottom: 15px; -} - @keyframes rotate { 0% { transform: rotate(0deg) @@ -531,3 +468,57 @@ input { transform: rotate(360deg) } } + +.button.collapse { + display: flex; + justify-content: space-between; +} + +.button.collapse::after { + display: block; + content: " "; + width: 20px; + height: 20px; + background-image: url("../icons/chevron-down-solid.svg"); + background-repeat: no-repeat; + 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; + transform: translate(-15px, calc(50% + 20px)); +} + +.button.collapse.open>div { + display: block; +} + +.button.collapse .button { + color: var(--offwhite); + background-color: var(--background-light); +} + +.button.collapse .button:hover { + color: var(--background); + background-color: var(--offwhite); +} + +.button.collapse .button:first-child { + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; +} + +.button.collapse .button:not(:first-child):not(:last-child) { + border-radius: 0px; +} + +.button.collapse .button:last-child { + border-top-left-radius: 0px; + border-top-right-radius: 0px; +}