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);
+ }
+
- <%= 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.
<% } %>
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}}
- GitHub
- Discord
+ User Guide
+ Troubleshooting Guide
+
+
+
+
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;
+}