Web UI: Create a system settings page

This commit is contained in:
Daniel Markstedt 2023-10-29 16:16:05 +09:00 committed by Daniel Markstedt
parent d1a080b7d0
commit e4c9b33778
8 changed files with 257 additions and 162 deletions

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22.61 16.95A5 5 0 0 0 18 10h-1.26a8 8 0 0 0-7.05-6M5 5a8 8 0 0 0 4 15h9a5 5 0 0 0 1.7-.3"/><line x1="1" y1="1" x2="23" y2="23"/></svg>

After

Width:  |  Height:  |  Size: 326 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 10h-1.26A8 8 0 1 0 9 20h9a5 5 0 0 0 0-10z"/></svg>

After

Width:  |  Height:  |  Size: 245 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 3a3 3 0 0 0-3 3v12a3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3H6a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3V6a3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3h12a3 3 0 0 0 3-3 3 3 0 0 0-3-3z"/></svg>

After

Width:  |  Height:  |  Size: 377 B

View File

@ -423,8 +423,8 @@ div.header div.authentication-disabled a {
color: #fff;
}
div.header div.login-status.logged-in a {
background: var(--danger) no-repeat right 0.5rem center;
div.header div.login-status.logged-in span.log-out-button a {
background: var(--primary) no-repeat right 0.5rem center;
background-image: url("icons/log-out.svg");
background-size: var(--icon-size);
border-radius: var(--border-radius);
@ -434,6 +434,17 @@ div.header div.authentication-disabled a {
color: #fff;
}
div.header div.login-status.logged-in span.admin-button a {
background: var(--secondary) no-repeat right 0.5rem center;
background-image: url("icons/command.svg");
background-size: var(--icon-size);
border-radius: var(--border-radius);
padding: 0.25rem 2.25rem 0.25rem 0.75rem;
display: inline-block;
text-decoration: none;
color: #fff;
}
div.header div.login-status.logged-in span.logged-in-as-text {
margin-right: 1rem;
}
@ -958,6 +969,29 @@ section#manual a p {
margin: 0;
}
/*
------------------------------------------------------------------------------
Admin > Section: Services
------------------------------------------------------------------------------
*/
section#services ul {
list-style: none;
padding-left: 0;
}
section#services li {
margin-bottom: 0.5em;
padding: 0.25rem 0 0.25rem 2rem;
}
section#services li.enabled {
background: url("icons/cloud.svg") no-repeat left center;
}
section#services li.disabled {
background: url("icons/cloud-off.svg") no-repeat left center;
}
/*
------------------------------------------------------------------------------
Drives page

View File

@ -0,0 +1,194 @@
{% extends "base.html" %}
{% block content %}
<section id="logging">
<details>
<summary class="heading">
{{ _("Logging") }}
</summary>
<ul>
<li>{{ _("The current dropdown selection indicates the active log level.") }}</li>
</ul>
</details>
<div>
<form action="/logs/show" method="post">
<label for="log_lines">{{ _("Log Lines:") }}</label>
<input name="lines" id="log_lines" type="number" value="200" min="0" max="99999" step="100">
<label for="log_scope">{{ _("Scope:") }}</label>
<select name="scope" id="log_scope">
<option value="">
{{ _("All logs") }}
</option>
<option value="piscsi">
piscsi
</option>
<option value="piscsi-web">
piscsi-web
</option>
<option value="piscsi-oled">
piscsi-oled
</option>
<option value="piscsi-ctrlboard">
piscsi-ctrlboard
</option>
</select>
<input type="submit" value="{{ _("Show Logs") }}">
</form>
</div>
<div>
<form action="/logs/level" method="post">
<label for="log_level">{{ _("Log Level:") }}</label>
<select name="level" id="log_level">
{% for level in log_levels %}
<option value="{{ level }}"{% if level == current_log_level %} selected{% endif %}>
{{ level }}
</option>
{% endfor %}
</select>
<input type="submit" value="{{ _("Set Log Level") }}">
</form>
</div>
</section>
<hr/>
<section id="appearance">
<details>
<summary class="heading">
{{ _("Appearance") }}
</summary>
<ul>
<li>{{ _("Theme and language are auto-detected for your user agent. Here you can change the default.") }}</li>
<li>{{ _("The System Name is the \"pretty\" hostname if set, with a fallback to the regular hostname.") }}</li>
</ul>
</details>
<div>
<div class="theme-change-hint">
{{ _("The current theme is \"%(theme)s\".", theme=current_theme) }}
{% if current_theme == "classic" %}
{{ _('Switch to the <a href="/theme?name=%(theme)s">%(theme)s theme</a>', theme="modern") }}
{% else %}
{{ _('Switch to the <a href="/theme?name=%(theme)s">%(theme)s theme</a>', theme="classic") }}
{% endif %}
</div>
<form action="/language" method="post">
<label for="locale">{{ _("Language:") }}</label>
<select name="locale" id="locale">
{% for locale in locales %}
{% if locale.language == env["locale"] %}
<option value="{{ locale.language }}" selected>
{% else %}
<option value="{{ locale.language }}">
{% endif %}
{{ locale.language }} - {{ locale.display_name }}
</option>
{% endfor %}
</select>
<input type="submit" value="{{ _("Change Language") }}">
</form>
</div>
<div>
<form action="/sys/rename" method="post">
<label for="system_name">{{ _("System Name:") }}</label>
<input name="system_name" id="system_name" type="text" maxlength=120 required value="{{ env['system_name'] }}">
<input type="submit" value="{{ _("Rename") }}">
</form>
<form action="/sys/rename" method="post">
<input name="system_name" type="hidden" value="">
<input type="submit" value="{{ _("Reset") }}">
</form>
</div>
</section>
<hr/>
<section id="services">
<details>
<summary class="heading">
{{ _("Companion Services") }}
</summary>
<ul>
<li>{{ _("If you want to add a service, run the easyinstall.sh script and choose the one to install.") }}</li>
<li>{{ _("In order to manage the services in the Web UI, you may install Webmin as well.") }}</li>
</ul>
</details>
<ul>
{% if netatalk_configured %}
<li class="enabled">
{{ _("Mac AFP file sharing is enabled.") }}
{% else %}
<li class="disabled">
{{ _("Mac AFP file sharing is disabled.") }}
{% endif %}
</li>
{% if webmin_configured %}
<li>
<a href="https://{{ env["ip_addr"] }}:10000/netatalk2/" target=\"_blank\">
{{ _("Manage the AFP server") }}
</a>
</li>
{% endif %}
{% if samba_configured %}
<li class="enabled">
{{ _("Windows SMB file sharing is enabled.") }}
{% else %}
<li class="disabled">
{{ _("Windows SMB file sharing is disabled.") }}
{% endif %}
</li>
{% if webmin_configured %}
<li>
<a href="https://{{ env["ip_addr"] }}:10000/samba/" target=\"_blank\">
{{ _("Manage the SMB server") }}
</a>
</li>
{% endif %}
{% if ftp_configured %}
<li class="enabled">
{{ _("FTP file sharing is enabled.") }}
{% else %}
<li class="disabled">
{{ _("FTP file sharing is disabled.") }}
{% endif %}
</li>
{% if macproxy_configured %}
<li class="enabled">
{{ _("Vintage web proxy is running at %(ip_addr)s (default port 5000)", ip_addr=env['ip_addr']) }}
{% else %}
<li class="disabled">
{{ _("Vintage web proxy is disabled.") }}
{% endif %}
</li>
</ul>
</section>
<hr/>
<section id="system">
<details>
<summary class="heading">
{{ _("System Operations") }}
</summary>
<ul>
<li>{{ _("IMPORTANT: Always shut down the system before turning off the power. Failing to do so may lead to data loss.") }}</li>
</ul>
</details>
<div class="power-control">
<form action="/sys/reboot" method="post" onclick="if (confirm('{{ _("Reboot the System?") }}')) shutdownNotify('{{ _("Rebooting the system...") }}'); else event.preventDefault();">
<input type="submit" value="{{ _("Reboot System") }}">
</form>
<form action="/sys/shutdown" method="post" onclick="if (confirm('{{ _("Shut Down the System?") }}')) shutdownNotify('{{ _("Shutting down the system...") }}'); else event.preventDefault();">
<input type="submit" value="{{ _("Shut Down System") }}">
</form>
</div>
</section>
<p class="home"><a href="/">{{ _("Go to Home") }}</a></p>
{% endblock content %}

View File

@ -32,7 +32,9 @@
<div align="center" class="login-status logged-in">
<span class="logged-in-as-text">{{ _("Logged in as <em>%(username)s</em>", username=env["username"]) }}</span>
<span class="separator">-</span>
<a href="/logout">{{ _("Log Out") }}</a>
<span class="log-out-button"><a href="/logout">{{ _("Log Out") }}</a></span>
<span class="separator">-</span>
<span class="admin-button"><a href="/sys/admin">{{ _("Settings") }}</a></span>
</div>
{% else %}
<div align="center" class="login-status logged-out">
@ -104,53 +106,6 @@
{% block content %}{% endblock content %}
</div>
<div align="center" class="footer">
<div class="theme-change-hint">
{% if current_theme == "classic" %}
{{ _('Switch to the <a href="/theme?name=%(theme)s">%(theme)s theme</a>', theme="modern") }}
{% else %}
{{ _('Switch to the <a href="/theme?name=%(theme)s">%(theme)s theme</a>', theme="classic") }}
{% endif %}
</div>
<div>
{% if env["netatalk_configured"] %}
{{ _("Mac AFP file sharing is enabled.") }}
{% if env["webmin_configured"] %}
<a href="https://{{ env["ip_addr"] }}:10000/netatalk2/" target=\"_blank\">
{{ ("Server administration") }}
</a>
{% endif %}
{% else %}
{{ _("Mac AFP file sharing is disabled.") }}
{% endif %}
</div>
<div>
{% if env["samba_configured"] %}
{{ _("Windows SMB file sharing is enabled.") }}
{% if env["webmin_configured"] %}
<a href="https://{{ env["ip_addr"] }}:10000/samba/" target=\"_blank\">
{{ ("Server administration") }}
</a>
{% endif %}
{% else %}
{{ _("Windows SMB file sharing is disabled.") }}
{% endif %}
</div>
<div>
{% if env["ftp_configured"] %}
{{ _("FTP file sharing is enabled.") }}
{% else %}
{{ _("FTP file sharing is disabled.") }}
{% endif %}
</div>
<div>
{% if env["macproxy_configured"] %}
{{ _("Macproxy is running at %(ip_addr)s (default port 5000)", ip_addr=env['ip_addr']) }}
{% else %}
{{ _("Macproxy is disabled.") }}
{% endif %}
</div>
<div>
{{ _("PiSCSI software version:") }} <b>{{ env["version"] }}</b>
</div>

View File

@ -570,7 +570,6 @@
<hr/>
<section id="logging">
<section id="attach-devices">
<details>
<summary class="heading">
@ -671,109 +670,6 @@
<hr/>
<details>
<summary class="heading">
{{ _("Logging") }}
</summary>
<ul>
<li>{{ _("The current dropdown selection indicates the active log level.") }}</li>
</ul>
</details>
<div>
<form action="/logs/show" method="post">
<label for="log_lines">{{ _("Log Lines:") }}</label>
<input name="lines" id="log_lines" type="number" value="200" min="0" max="99999" step="100">
<label for="log_scope">{{ _("Scope:") }}</label>
<select name="scope" id="log_scope">
<option value="">
{{ _("All logs") }}
</option>
<option value="piscsi">
piscsi
</option>
<option value="piscsi-web">
piscsi-web
</option>
<option value="piscsi-oled">
piscsi-oled
</option>
<option value="piscsi-ctrlboard">
piscsi-ctrlboard
</option>
</select>
<input type="submit" value="{{ _("Show Logs") }}">
</form>
</div>
<div>
<form action="/logs/level" method="post">
<label for="log_level">{{ _("Log Level:") }}</label>
<select name="level" id="log_level">
{% for level in log_levels %}
<option value="{{ level }}"{% if level == current_log_level %} selected{% endif %}>
{{ level }}
</option>
{% endfor %}
</select>
<input type="submit" value="{{ _("Set Log Level") }}">
</form>
</div>
</section>
<hr/>
<section id="system">
<details>
<summary class="heading">
{{ _("System Operations") }}
</summary>
<ul>
<li>{{ _("The System Name is the \"pretty\" hostname if set, with a fallback to the regular hostname.") }}</li>
<li>{{ _("IMPORTANT: Always shut down the system before turning off the power. Failing to do so may lead to data loss.") }}</li>
</ul>
</details>
<div>
<form action="/language" method="post">
<label for="locale">{{ _("Language:") }}</label>
<select name="locale" id="locale">
{% for locale in locales %}
{% if locale.language == env['locale'] %}
<option value="{{ locale.language }}" selected="selected">
{% else %}
<option value="{{ locale.language }}">
{% endif %}
{{ locale.language }} - {{ locale.display_name }}
</option>
{% endfor %}
</select>
<input type="submit" value="{{ _("Change Language") }}">
</form>
</div>
<div>
<form action="/sys/rename" method="post">
<label for="system_name">{{ _("System Name:") }}</label>
<input name="system_name" id="system_name" type="text" maxlength=120 required>
<input type="submit" value="{{ _("Rename") }}">
</form>
<form action="/sys/rename" method="post">
<input name="system_name" type="hidden" value="">
<input type="submit" value="{{ _("Reset") }}">
</form>
</div>
<div class="power-control">
<form action="/sys/reboot" method="post" onclick="if (confirm('{{ _("Reboot the System?") }}')) shutdownNotify('{{ _("Rebooting the system...") }}'); else event.preventDefault();">
<input type="submit" value="{{ _("Reboot System") }}">
</form>
<form action="/sys/shutdown" method="post" onclick="if (confirm('{{ _("Shut Down the System?") }}')) shutdownNotify('{{ _("Shutting down the system...") }}'); else event.preventDefault();">
<input type="submit" value="{{ _("Shut Down System") }}">
</form>
</div>
</section>
<hr/>
<section id="manual">
<a href="/sys/manpage?app=piscsi"><p>{{ _("Read the PiSCSI Manual") }}</p></a>
</section>

View File

@ -124,11 +124,6 @@ def get_env_info():
"version": server_info["version"],
"image_dir": server_info["image_dir"],
"image_root_dir": Path(server_info["image_dir"]).name,
"netatalk_configured": sys_cmd.running_proc("afpd"),
"samba_configured": sys_cmd.running_proc("smbd"),
"ftp_configured": sys_cmd.running_proc("vsftpd"),
"macproxy_configured": sys_cmd.running_proc("macproxy"),
"webmin_configured": sys_cmd.running_proc("miniserv.pl"),
"cd_suffixes": tuple(server_info["sccd"]),
"rm_suffixes": tuple(server_info["scrm"]),
"mo_suffixes": tuple(server_info["scmo"]),
@ -264,7 +259,6 @@ def index():
return response(
template="index.html",
page_title=_("PiSCSI Control Page"),
locales=get_supported_locales(),
netinfo=piscsi_cmd.get_network_info(),
bridge_configured=sys_cmd.is_bridge_setup(),
devices=formatted_devices,
@ -274,8 +268,6 @@ def index():
config_files=config_files,
device_types=device_types,
scan_depth=server_info["scan_depth"],
log_levels=server_info["log_levels"],
current_log_level=server_info["current_log_level"],
scsi_ids=scsi_ids,
units=units,
reserved_scsi_ids=reserved_scsi_ids,
@ -321,6 +313,27 @@ def drive_list():
)
@APP.route("/sys/admin", methods=["GET"])
def admin():
"""
Sets up the data structures and kicks off the rendering of the system admin page
"""
server_info = piscsi_cmd.get_server_info()
return response(
template="admin.html",
page_title=_("PiSCSI System Administration"),
log_levels=server_info["log_levels"],
current_log_level=server_info["current_log_level"],
locales=get_supported_locales(),
netatalk_configured=sys_cmd.running_proc("afpd"),
samba_configured=sys_cmd.running_proc("smbd"),
ftp_configured=sys_cmd.running_proc("vsftpd"),
macproxy_configured=sys_cmd.running_proc("macproxy"),
webmin_configured=sys_cmd.running_proc("miniserv.pl"),
)
@APP.route("/upload", methods=["GET"])
def upload_page():
"""