Feature/background color (#107)

* Add enable/disable fog variable

* Add background color variable

* Add background in setup

* Populate defaults for enableFog and backgroundColor as a migration step

* add tool tip

---------

Co-authored-by: Antony Leons <antony@leons.dev>
This commit is contained in:
Nicandros Nic 2024-02-24 18:59:42 +01:00 committed by GitHub
parent 0de0cf8577
commit 7a8d4cd653
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 191 additions and 39 deletions

View File

@ -71,11 +71,13 @@ Ward works nice on all popular operating systems, because it uses [OSHI](https:/
If you want to change Ward's configuration, you can edit `setup.ini`. When using Docker, use the environment variables `WARD_NAME`,`WARD_THEME`, `WARD_PORT` to automatically regenerate this file at startup. Using any environment variable listed will enable the defaults below and immediately start Ward without the GUI setup. If you want to change Ward's configuration, you can edit `setup.ini`. When using Docker, use the environment variables `WARD_NAME`,`WARD_THEME`, `WARD_PORT` to automatically regenerate this file at startup. Using any environment variable listed will enable the defaults below and immediately start Ward without the GUI setup.
| Setting | Description | Default | | Setting | Env var | Description | Default |
|------------|------------------------------|---------| |-----------------|-----------------|----------------------------------------------|---------|
| serverName | Name shown in the interface. | Ward | | serverName | WARD_NAME | Name shown in the interface. | Ward |
| theme | Either `light` or `dark`. | light | | port | WARD_PORT | Port to listen on. | 4000 |
| port | Port to listen on. | 4000 | | theme | WARD_THEME | Either `light` or `dark`. | light |
| enableFog | WARD_FOG | Either `true` or `false`. | true |
| backgroundColor | WARD_BACKGROUND | HexColor for background when fog is disabled | default |
Environment variables take priority and will regenerate this file with your variables. If no environment variables are set, `setup.ini` is generated once you navigate to Ward's webpage and complete the initial setup. You can also make this file yourself before starting Ward, and place it in the same directory. Environment variables take priority and will regenerate this file with your variables. If no environment variables are set, `setup.ini` is generated once you navigate to Ward's webpage and complete the initial setup. You can also make this file yourself before starting Ward, and place it in the same directory.
@ -86,4 +88,6 @@ For example:
serverName = my-server serverName = my-server
theme = dark theme = dark
port = 8200 port = 8200
enableFog = true
backgroundColor = #303030
``` ```

View File

@ -9,5 +9,7 @@ services:
- WARD_PORT=4000 - WARD_PORT=4000
- WARD_THEME=dark - WARD_THEME=dark
- WARD_NAME=leons-server - WARD_NAME=leons-server
- WARD_FOG=false
- WARD_BACKGROUND=#3c3c3c
privileged: true privileged: true
image: antonyleons/ward image: antonyleons/ward

View File

@ -6,7 +6,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>dev.leons</groupId> <groupId>dev.leons</groupId>
<artifactId>ward</artifactId> <artifactId>ward</artifactId>
<version>2.4.1</version> <version>2.5.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<!-- parent pom --> <!-- parent pom -->

View File

@ -51,7 +51,7 @@ public class Ward extends SpringBootServletInitializer {
File setupFile = new File(Ward.SETUP_FILE_PATH); File setupFile = new File(Ward.SETUP_FILE_PATH);
if (System.getenv("WARD_NAME") != null || (System.getenv("WARD_THEME") != null) || (System.getenv("WARD_PORT") != null)) { if (System.getenv("WARD_NAME") != null || (System.getenv("WARD_THEME") != null) || (System.getenv("WARD_PORT") != null) || (System.getenv("WARD_FOG") != null)) {
SetupService.envSetup(); SetupService.envSetup();
} else if (setupFile.exists()) { } else if (setupFile.exists()) {
restart(); restart();

View File

@ -9,12 +9,12 @@ import java.io.IOException;
/** /**
* UtilitiesComponent provides various functions, which are used in different classes * UtilitiesComponent provides various functions, which are used in different classes
*
* @author Rudolf Barbu * @author Rudolf Barbu
* @version 1.0.2 * @version 1.0.2
*/ */
@Component @Component
public class UtilitiesComponent public class UtilitiesComponent {
{
/** /**
* Constant, that providing setup section name * Constant, that providing setup section name
*/ */
@ -25,19 +25,36 @@ public class UtilitiesComponent
* *
* @param optionName option in section * @param optionName option in section
* @return String wth parsed data * @return String wth parsed data
* @throws IOException if file does not exists * @throws IOException if file does not exist
*/ */
@SuppressWarnings(value = "MismatchedQueryAndUpdateOfCollection") @SuppressWarnings(value = "MismatchedQueryAndUpdateOfCollection")
public String getFromIniFile(final String optionName) throws IOException public String getFromIniFile(final String optionName) throws IOException {
{ final File file = new File(Ward.SETUP_FILE_PATH);
File file = new File(Ward.SETUP_FILE_PATH);
if (file.exists()) if (file.exists()) {
{ final Ini ini = new Ini(file);
Ini ini = new Ini(file);
return ini.get(SECTION_NAME, optionName, String.class); return ini.get(SECTION_NAME, optionName, String.class);
} }
return null; return null;
} }
/**
* Sets string data to the ini file
*
* @param optionName option in section
* @param value value to put
* @throws IOException if file does not exist
*/
public void putInIniFile(final String optionName, final String value) throws IOException {
final File file = new File(Ward.SETUP_FILE_PATH);
if (file.exists()) {
final Ini ini = new Ini(file);
ini.put(SECTION_NAME, optionName, value);
ini.store();
} else {
throw new IOException();
}
}
} }

View File

@ -42,4 +42,19 @@ public class SetupDto
@Min(value = 10) @Min(value = 10)
@Max(value = 65535) @Max(value = 65535)
private String port; private String port;
/**
* Enable fog field
*/
@NotNull
@NotEmpty
@Pattern(regexp = "true|false")
private String enableFog;
/**
* Background Color field
*/
@NotEmpty
@Pattern(regexp = "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$|default")
private String backgroundColor;
} }

View File

@ -78,8 +78,12 @@ public class IndexService
return "setup"; return "setup";
} }
updateDefaultsInSetupFile();
model.addAttribute("theme", utilitiesComponent.getFromIniFile("theme")); model.addAttribute("theme", utilitiesComponent.getFromIniFile("theme"));
model.addAttribute("serverName", utilitiesComponent.getFromIniFile("serverName")); model.addAttribute("serverName", utilitiesComponent.getFromIniFile("serverName"));
model.addAttribute("enableFog", utilitiesComponent.getFromIniFile("enableFog"));
model.addAttribute("backgroundColor", utilitiesComponent.getFromIniFile("backgroundColor"));
model.addAttribute("info", infoService.getInfo()); model.addAttribute("info", infoService.getInfo());
model.addAttribute("uptime", uptimeService.getUptime()); model.addAttribute("uptime", uptimeService.getUptime());
@ -87,4 +91,13 @@ public class IndexService
return "index"; return "index";
} }
private void updateDefaultsInSetupFile() throws IOException {
if (utilitiesComponent.getFromIniFile("enableFog") == null) {
utilitiesComponent.putInIniFile("enableFog", "true");
}
if (utilitiesComponent.getFromIniFile("backgroundColor") == null) {
utilitiesComponent.putInIniFile("backgroundColor", "#303030");
}
}
} }

View File

@ -51,6 +51,8 @@ public class SetupService {
putInIniFile(file, "serverName", setupDto.getServerName()); putInIniFile(file, "serverName", setupDto.getServerName());
putInIniFile(file, "theme", setupDto.getTheme()); putInIniFile(file, "theme", setupDto.getTheme());
putInIniFile(file, "port", setupDto.getPort()); putInIniFile(file, "port", setupDto.getPort());
putInIniFile(file, "enableFog", setupDto.getEnableFog());
putInIniFile(file, "backgroundColor", setupDto.getBackgroundColor());
Ward.restart(); Ward.restart();
} else { } else {
@ -74,10 +76,14 @@ public class SetupService {
String servername = (System.getenv("WARD_NAME") != null) ? System.getenv("WARD_NAME") : "Ward"; String servername = (System.getenv("WARD_NAME") != null) ? System.getenv("WARD_NAME") : "Ward";
String theme = (System.getenv("WARD_THEME") != null) ? System.getenv("WARD_THEME").toLowerCase() : "light"; String theme = (System.getenv("WARD_THEME") != null) ? System.getenv("WARD_THEME").toLowerCase() : "light";
String port = (System.getenv("WARD_PORT") != null) ? System.getenv("WARD_PORT") : "4000"; String port = (System.getenv("WARD_PORT") != null) ? System.getenv("WARD_PORT") : "4000";
String enableFog = (System.getenv("WARD_FOG") != null) ? System.getenv("WARD_FOG") : "true";
String backgroundColor = (System.getenv("WARD_BACKGROUND") != null) ? System.getenv("WARD_BACKGROUND") : "default";
putInIniFile(file, "serverName", servername); putInIniFile(file, "serverName", servername);
putInIniFile(file, "theme", theme); putInIniFile(file, "theme", theme);
putInIniFile(file, "port", port); putInIniFile(file, "port", port);
putInIniFile(file, "enableFog", enableFog);
putInIniFile(file, "backgroundColor", backgroundColor);
Ward.restart(); Ward.restart();
} else { } else {

View File

@ -24,8 +24,9 @@
--top-label-additional-settings: 2.3rem; --top-label-additional-settings: 2.3rem;
--top-additional-settings: 1rem; --top-additional-settings: 1rem;
--top-theme-buttons-input: 1.938rem; --top-theme-buttons-input: 1.938rem;
--top-background-settings: 2.938rem;
--top-button-squares-grid: 0.222rem; --top-button-squares-grid: 0.222rem;
--top-port: 2.75rem; --top-port: 2.7rem;
--top-header: 1.5rem; --top-header: 1.5rem;
--top-label-hw-info: 0.562rem; --top-label-hw-info: 0.562rem;
--top-card-body-squares-grid: 0.813rem; --top-card-body-squares-grid: 0.813rem;
@ -65,7 +66,9 @@
--left-main-settings: 1.5rem; --left-main-settings: 1.5rem;
--left-button-squares-grid-first: 1.5rem; --left-button-squares-grid-first: 1.5rem;
--left-button-squares-grid-second: 19.688rem; --left-button-squares-grid-second: 19.688rem;
--left-background-settings: 1.5rem;
--left-theme-buttons-first: 1.5rem; --left-theme-buttons-first: 1.5rem;
--left-background-settings-color-selector: 1.5rem;
--left-port: 1.5rem; --left-port: 1.5rem;
--left-submit: 6.563rem; --left-submit: 6.563rem;
--left-header: 1.5rem; --left-header: 1.5rem;
@ -116,16 +119,17 @@
/* height */ /* height */
--height-body: 100%; --height-body: 100%;
--height-setup: 26.706rem; --height-setup: 26.706rem;
--height-setup-div: 26.706rem; --height-setup-div: 32.706rem;
--height-clouds: 8.281rem; --height-clouds: 8.281rem;
--height-clouds-img: 5.438rem; --height-clouds-img: 5.438rem;
--height-background: 8.281rem; --height-background: 8.281rem;
--height-form: 18.425rem; --height-form: 24.425rem;
--height-form-squares-grid-div: 0.625rem; --height-form-squares-grid-div: 0.625rem;
--height-main-settings: 1.875rem; --height-main-settings: 1.875rem;
--height-main-settings-underline: 0.313rem; --height-main-settings-underline: 0.313rem;
--height-main-settings-select: 1.875rem; --height-main-settings-select: 1.875rem;
--height-theme-buttons-input: 2.188rem; --height-theme-buttons-input: 2.188rem;
--height-background-settings: 2.188rem;
--height-button-squares-grid-div: 0.625rem; --height-button-squares-grid-div: 0.625rem;
--height-port: 3.125rem; --height-port: 3.125rem;
--height-submit: 1.875rem; --height-submit: 1.875rem;
@ -178,6 +182,7 @@
--width-main-settings-underline: 18.875rem; --width-main-settings-underline: 18.875rem;
--width-main-settings-select: 18.875rem; --width-main-settings-select: 18.875rem;
--width-theme-buttons-input: 9.063rem; --width-theme-buttons-input: 9.063rem;
--width-background-settings-input: 9.063rem;
--width-button-squares-grid-div: 0.625rem; --width-button-squares-grid-div: 0.625rem;
--width-port: 18.875rem; --width-port: 18.875rem;
--width-submit: 8.75rem; --width-submit: 8.75rem;

View File

@ -280,6 +280,35 @@ body {
background: var(--background-theme-buttons-second); background: var(--background-theme-buttons-second);
} }
.additional-settings > label {
top: var(--top-background-settings);
left: var(--left-background-settings);
height: var(--height-background-settings);
white-space: nowrap;
}
.additional-settings > label > input {
vertical-align: middle;
position: relative;
left: var(--left-background-settings);
border-style: none;
}
.additional-settings > label > span {
vertical-align: middle;
position: relative;
}
.additional-settings > .color-selector {
display: block;
position: relative;
margin-top: var(--height-background-settings);
left: var(--left-background-settings-color-selector);
width: var(--width-background-settings-input);
background: var(--background-background-settings-color-selector);
box-shadow: var(--box-shadow-background-settings-input) var(--black-opacity-10);
}
.port { .port {
position: relative; position: relative;
top: var(--top-port); top: var(--top-port);

View File

@ -20,6 +20,7 @@
--box-shadow-main-settings-underline: 0.000rem 0.188rem 0.313rem 0.000rem; --box-shadow-main-settings-underline: 0.000rem 0.188rem 0.313rem 0.000rem;
--box-shadow-button-squares-grid-div: 0.000rem 0.188rem 0.313rem 0.000rem; --box-shadow-button-squares-grid-div: 0.000rem 0.188rem 0.313rem 0.000rem;
--box-shadow-theme-buttons-input: 0.000rem 0.188rem 0.313rem 0.000rem; --box-shadow-theme-buttons-input: 0.000rem 0.188rem 0.313rem 0.000rem;
--box-shadow-background-settings-input: 0.000rem 0.188rem 0.313rem 0.000rem;
--box-shadow-submit: 0.000rem 0.188rem 0.313rem 0.000rem; --box-shadow-submit: 0.000rem 0.188rem 0.313rem 0.000rem;
--box-shadow-card: 0.000rem 0.313rem 0.625rem 0.000rem; --box-shadow-card: 0.000rem 0.313rem 0.625rem 0.000rem;
--box-shadow-uptime-squares-grid-div: 0.000rem 0.188rem 0.313rem 0.000rem; --box-shadow-uptime-squares-grid-div: 0.000rem 0.188rem 0.313rem 0.000rem;

View File

@ -63,6 +63,7 @@ html[theme = "light"]
--background-button-squares-grid-second: var(--grey-light); --background-button-squares-grid-second: var(--grey-light);
--background-theme-buttons-first: var(--purple-light); --background-theme-buttons-first: var(--purple-light);
--background-theme-buttons-second: var(--grey-light); --background-theme-buttons-second: var(--grey-light);
--background-background-settings-color-selector: var(--grey-light);
--background-port: var(--white); --background-port: var(--white);
--background-submit: var(--green-light); --background-submit: var(--green-light);
--background-card: var(--white); --background-card: var(--white);
@ -148,6 +149,7 @@ html[theme = "dark"]
--background-button-squares-grid-second: var(--grey-light); --background-button-squares-grid-second: var(--grey-light);
--background-theme-buttons-first: var(--purple-light); --background-theme-buttons-first: var(--purple-light);
--background-theme-buttons-second: var(--grey-light); --background-theme-buttons-second: var(--grey-light);
--background-background-settings-color-selector: var(--grey-light);
--background-port: var(--grey); --background-port: var(--grey);
--background-submit: var(--grey-light); --background-submit: var(--grey-light);
--background-card: var(--grey-dark); --background-card: var(--grey-dark);

View File

@ -5,26 +5,42 @@
*/ */
function backgroundInitialization() function backgroundInitialization()
{ {
background = VANTA.FOG({el: "#background", blurFactor: 0.40, zoom: 1.50}); if (html.getAttribute("enableFog") == "true")
if (html.getAttribute("theme") == "light")
{ {
background.setOptions background = VANTA.FOG({el: "#background", blurFactor: 0.40, zoom: 1.50});
({ if (html.getAttribute("theme") == "light")
highlightColor: 0xCAC7E8, {
midtoneColor: 0xBBB7ED, background.setOptions
lowlightColor: 0xE4E3EF, ({
baseColor: 0xE4E3EF highlightColor: 0xCAC7E8,
}); midtoneColor: 0xBBB7ED,
lowlightColor: 0xE4E3EF,
baseColor: 0xE4E3EF
});
}
else
{
background.setOptions
({
highlightColor: 0x797979,
midtoneColor: 0xFFFFFF,
lowlightColor: 0xBCBCBC,
baseColor: 0xBCBCBC
});
}
} }
else else
{ {
background.setOptions if (background){
({ background.destroy();
highlightColor: 0x797979, }
midtoneColor: 0xFFFFFF, if (html.getAttribute("backgroundColor") == "default" )
lowlightColor: 0xBCBCBC, {
baseColor: 0xBCBCBC document.body.style.backgroundColor = html.getAttribute("theme") == "light" ? "#e5e5e5" : "#303030"
}); }
else
{
document.body.style.backgroundColor = html.getAttribute("backgroundColor")
}
} }
} }

View File

@ -10,6 +10,17 @@ let html;
*/ */
let background; let background;
/**
* Used to determine background color
*/
let backgroundColor;
/**
* Used to determine if we enable the fog
*/
let enableFog;
/** /**
* Light theme square * Light theme square
*/ */

View File

@ -16,12 +16,16 @@ function setupInitialization()
serverName = document.getElementById("server-name"); serverName = document.getElementById("server-name");
port = document.getElementById("port"); port = document.getElementById("port");
enableFog = document.getElementById("fog-toggle");
backgroundColor = document.getElementById("color-selector");
setupXHR = new XMLHttpRequest(); setupXHR = new XMLHttpRequest();
lightTheme.addEventListener("click", function(event) {changeTheme(event.target || event.srcElement)}); lightTheme.addEventListener("click", function(event) {changeTheme(event.target || event.srcElement)});
darkTheme.addEventListener("click", function(event) {changeTheme(event.target || event.srcElement)}); darkTheme.addEventListener("click", function(event) {changeTheme(event.target || event.srcElement)});
submit.addEventListener("click", function(event) {sendSetupRequest(event.target || event.srcElement)}); submit.addEventListener("click", function(event) {sendSetupRequest(event.target || event.srcElement)});
enableFog.addEventListener("change", function(event) {toggleFog()});
backgroundColor.addEventListener("input", function(event) {changeBackgroundColor()});
} }
/** /**
@ -63,6 +67,10 @@ function changeTheme(element)
baseColor: 0xBCBCBC baseColor: 0xBCBCBC
}); });
} }
let color = html.getAttribute("theme") == "light" ? "#e5e5e5" : "#303030";
html.setAttribute("backgroundColor", color);
backgroundColor.value = color;
document.body.style.backgroundColor = color;
} }
/** /**
@ -117,9 +125,30 @@ function sendSetupRequest()
{ {
"serverName": serverName.value, "serverName": serverName.value,
"theme": html.getAttribute("theme"), "theme": html.getAttribute("theme"),
"port": port.value "port": port.value,
"enableFog": String(enableFog.checked),
"backgroundColor": backgroundColor.value
} }
setupXHR.send(JSON.stringify(data)); setupXHR.send(JSON.stringify(data));
}
/**
* Toggles fog
*/
function toggleFog()
{
html.setAttribute("enableFog", String(enableFog.checked));
backgroundInitialization();
backgroundColor.disabled = enableFog.checked;
}
/**
* Change background color
*/
function changeBackgroundColor()
{
html.setAttribute("backgroundColor", backgroundColor.value);
document.body.style.backgroundColor = backgroundColor.value;
} }

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns:th = "http://www.thymeleaf.org" id = "html" lang = "en" th:attr = "theme = ${theme}"> <html xmlns:th = "http://www.thymeleaf.org" id = "html" lang = "en" th:attr = "theme = ${theme}, enableFog = ${enableFog}, backgroundColor = ${backgroundColor}">
<head> <head>
<meta charset = "UTF-8"> <meta charset = "UTF-8">
<title th:text = "${serverName}"></title> <title th:text = "${serverName}"></title>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns:th = "http://www.thymeleaf.org" id = "html" theme = "light"> <html xmlns:th = "http://www.thymeleaf.org" id = "html" theme = "light" enableFog = "true" backgroundColor = "default">
<head> <head>
<meta charset = "UTF-8"> <meta charset = "UTF-8">
<title>Welcome</title> <title>Welcome</title>
@ -66,6 +66,8 @@
<input id = "light-theme" class = "first" type = "button" value = "LIGHT THEME" /> <input id = "light-theme" class = "first" type = "button" value = "LIGHT THEME" />
<input id = "dark-theme" class = "second" type = "button" value = "DARK THEME" /> <input id = "dark-theme" class = "second" type = "button" value = "DARK THEME" />
</div> </div>
<label class = "label-additional-settings"><span>ENABLE BACKGROUND FOG</span><input id = "fog-toggle" class = "fog-toggle" type = "checkbox" name = "enableFog" checked></label>
<label class = "label-additional-settings" title="Disable Fog to select"><span>SELECT BACKGROUND COLOR</span><input id = "color-selector" class = "color-selector" type = "color" value="#e5e5e5" disabled></label>
<input id = "port" class = "port" type = "text" maxlength = "5" placeholder = "Application Port" /> <input id = "port" class = "port" type = "text" maxlength = "5" placeholder = "Application Port" />
</div> </div>
<input id = "submit" class = "submit" type = "button" value = "LAUNCH" /> <input id = "submit" class = "submit" type = "button" value = "LAUNCH" />