Address Sonarcloud issues for the html code; improve on css styles (#892)

Refactor and clean up code to conform to SonarCloud static analysis, improve readability and semantics.
- Add labels for each form input, and tweak placeholder text accordingly.
- Move CSS styles to the stylesheet; minor tweaks for clarity and consistency
- Use the legacy align=center attribute for centering paragraphs (backwards compatible)
- Remove all instances of using tables for layout
- Add header tags to all remaining tables, with scope parameters.
- Add descriptions to each table
- Move drive reference hyperlinks to the drive name column (addresses "same link text leads to different URL" code smell.)
- Inject lang parameters to each html tag
- Standardize on h2 tags as top header for each template
- Add 'json' to config file UI elements, to communicate actual file name/format
- Clean up indentation
- Dropbox styling: Added a colored outline, added padding to more clearly communicate its function. Hid the (X) SVG that indicates failure, since failure is already communicated by the error text. Also, the SVG always obstructed the file name or error so was quite counter-productive.
This commit is contained in:
Daniel Markstedt 2022-10-07 13:13:29 -07:00 committed by GitHub
parent 90ace5fd53
commit d1a703418c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 469 additions and 491 deletions

View File

@ -2,19 +2,7 @@ body {
color: black;
background-color: white;
font-family: Arial, Helvetica, sans-serif;
text-decoration:none;
}
h1 {
color: white;
font-size:20px;
background-color:black;
}
h2 {
color: black;
font-size:16px;
margin: 0px;
text-decoration: none;
}
a {
@ -27,10 +15,50 @@ form {
table, tr, td {
border: 1px solid black;
border-collapse:collapse;
border-collapse: collapse;
margin: none;
}
h1 {
color: white;
font-size: 20px;
}
h2 {
color: black;
font-size: large;
font-weight: bold;
margin: 3px;
}
summary.heading {
color: black;
font-size: large;
font-weight: bold;
margin: 3px;
}
div.header {
color: white;
background-color: black;
}
div.footer {
font-family: monospace;
}
div.logged_in {
background-color: green;
}
div.logged_out {
background-color: red;
}
input.lun {
width: 36px;
}
div.flash {
margin-top: 5px;
margin-bottom: 5px;
@ -61,71 +89,76 @@ div.flash div.info {
}
td.inactive {
text-align:center;
background-color:tan;
text-align: center;
background-color: tan;
}
summary.heading {
color: black;
font-size: large;
font-weight: bold;
margin: 0px;
ul.inline_list {
list-style: none;
}
.dropzone, .dropzone * {
box-sizing: border-box;
box-sizing: border-box;
}
.dropzone {
position: relative;
position: relative;
}
.dropzone .dz-button {
position: relative;
background-color: white;
color: black;
border: 2px dashed blue;
padding: 12px 28px;
}
.dropzone .dz-preview {
position: relative;
display: inline-block;
width: 120px;
margin: .5em;
position: relative;
display: inline-block;
width: 120px;
margin: .5em;
}
.dropzone .dz-preview .dz-progress {
display: block;
height: 15px;
border: 1px solid #aaa;
display: block;
height: 15px;
border: 1px solid #aaa;
}
.dropzone .dz-preview .dz-progress .dz-upload {
display: block;
height: 100%;
width: 0;
background: green;
display: block;
height: 100%;
width: 0;
background: green;
}
.dropzone .dz-preview .dz-error-message {
color: red;
display: none;
color: red;
display: none;
}
.dropzone .dz-preview.dz-error .dz-error-message {
display: block;
display: block;
}
.dropzone .dz-preview.dz-error .dz-error-mark {
display: block;
filter: drop-shadow(0px 0px 2px red);
display: block;
filter: drop-shadow(0px 0px 2px red);
opacity: 0;
}
.dropzone .dz-preview.dz-success .dz-success-mark {
display: block;
filter: drop-shadow(0px 0px 2px green);
display: block;
filter: drop-shadow(0px 0px 2px green);
}
.dropzone .dz-preview .dz-error-mark, .dropzone .dz-preview .dz-success-mark {
position: absolute;
display: none;
left: 30px;
top: 30px;
width: 54px;
height: 58px;
left: 50%;
margin-left: -27px;
position: absolute;
display: none;
top: 30px;
width: 54px;
height: 58px;
left: 50%;
margin-left: -27px;
}

View File

@ -1,80 +1,76 @@
<!doctype html>
<html>
<html lang="{{ env["locale"] }}">
<head>
<title>{{ _("RaSCSI Reloaded Control Page") }} [{{ env["host"] }}]</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<link rel="apple-touch-icon" sizes="57x57" href="/pwa/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/pwa/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/pwa/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/pwa/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/pwa/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/pwa/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/pwa/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/pwa/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/pwa/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192" href="/pwa/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="/pwa/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="/pwa/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="/pwa/favicon-16x16.png">
<link rel="manifest" href="/pwa/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="/pwa/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<link rel="apple-touch-icon" sizes="57x57" href="/pwa/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/pwa/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/pwa/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/pwa/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/pwa/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/pwa/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/pwa/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/pwa/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/pwa/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192" href="/pwa/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="/pwa/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="/pwa/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="/pwa/favicon-16x16.png">
<link rel="manifest" href="/pwa/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="/pwa/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<script type="application/javascript">
var processNotify = function(Notification) {
document.getElementById("flash").innerHTML = "<div class=\"info\">" + Notification + "{{ _(" This process may take a while, and will continue in the background if you navigate away from this page.") }}</div>";
window.scrollTo(0,0);
}
<script type="application/javascript">
var processNotify = function(Notification) {
document.getElementById("flash").innerHTML = "<div class=\"info\">" + Notification + "{{ _(" This process may take a while, and will continue in the background if you navigate away from this page.") }}</div>";
window.scrollTo(0,0);
}
var shutdownNotify = function(Notification) {
document.getElementById("flash").innerHTML = "<div class=\"info\">" + Notification + "{{ _(" The Web Interface will become unresponsive momentarily. Reload this page after the Pi has started up again.") }}</div>";
window.scrollTo(0,0);
}
</script>
<script type="application/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.3/min/dropzone.min.js"></script>
var shutdownNotify = function(Notification) {
document.getElementById("flash").innerHTML = "<div class=\"info\">" + Notification + "{{ _(" The Web Interface will become unresponsive momentarily. Reload this page after the Pi has started up again.") }}</div>";
window.scrollTo(0,0);
}
</script>
<script type="application/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.3/min/dropzone.min.js"></script>
</head>
<body>
<div class="content">
<div class="header">
{% if env["auth_active"] %}
{% if env["username"] %}
<span style="display: inline-block; width: 100%; color: white; background-color: green; text-align: center; vertical-align: center; font-family: Arial, Helvetica, sans-serif;">{{ _("Logged in as <em>%(username)s</em>", username=env["username"]) }} &#8211; <a href="/logout">{{ _("Log Out") }}</a></span>
<div align="center" class="logged_in">
{{ _("Logged in as <em>%(username)s</em>", username=env["username"]) }} - <a href="/logout">{{ _("Log Out") }}</a>
</div>
{% else %}
<span style="display: inline-block; width: 100%; color: white; background-color: red; text-align: center; vertical-align: center; font-family: Arial, Helvetica, sans-serif;">
<div align="center" class="logged_out">
<form method="POST" action="/login">
<div>{{ _("Log In to Use Web Interface") }}</div>
<input type="text" name="username" placeholder="{{ _("Username") }}">
<input type="password" name="password" placeholder="{{ _("Password") }}">
<label for="username">{{ _("Username") }}</label>
<input type="text" name="username" id="username">
<label for="password">{{ _("Password") }}</label>
<input type="password" name="password" id="password">
<input type="submit" value="Login">
</form>
</span>
</div>
{% endif %}
{% else %}
<span style="display: inline-block; width: 100%; color: white; background-color: green; text-align: center; vertical-align: center; font-family: Arial, Helvetica, sans-serif;">{{ _("Web Interface Authentication Disabled") }} &#8211; {{ _("See <a href=\"%(url)s\" target=\"_blank\">Wiki</a> for more information", url="https://github.com/akuker/RASCSI/wiki/Web-Interface#enable-authentication") }}</span>
<div align="center" class="logged_out">
{{ _("Web Interface Authentication Disabled") }} - {{ _("See <a href=\"%(url)s\" target=\"_blank\">Wiki</a> for more information", url="https://github.com/akuker/RASCSI/wiki/Web-Interface#enable-authentication") }}
</div>
{% endif %}
<table width="100%" style="background-color: black;">
<tbody>
<tr align="center">
<td>
<a href="/">
<h1>{{ _("RaSCSI Reloaded Control Page") }}</h1>
</a>
</td>
</tr>
<tr>
<td style="color: white;">
hostname: {{ env["host"] }} ip: {{ env["ip_addr"] }}
</td>
</tr>
</tbody>
</table>
<div align="center">
<a href="/">
<h1>{{ _("RaSCSI Reloaded Control Page") }}</h1>
</a>
</div>
<div>
hostname: {{ env["host"] }} ip: {{ env["ip_addr"] }}
</div>
</div>
<div class="flash" id="flash">
{% for category, message in get_flashed_messages(with_categories=true) %}
@ -88,9 +84,27 @@
<div class="content">
{% block content %}{% endblock content %}
</div>
<div class="footer">
<center><tt>{{ _("RaSCSI Reloaded version: ") }}<strong>{{ version }} <a href="https://github.com/akuker/RASCSI/commit/{{ env["running_env"]["git"] }}" target="_blank">{{ env["running_env"]["git"][:7] }}</a></strong></tt></center>
<center><tt>{{ _("Pi environment: ") }}{{ env["running_env"]["env"] }}</tt></center>
<div align="center" class="footer">
<div>
{% if env["netatalk_configured"] == 1 %}
{{ _("The AppleShare server is running. No active connections.") }}
{% endif %}
{% if env["netatalk_configured"] == 2 %}
{{ _("%(value)d active AFP connection", value=(env["netatalk_configured"] - 1)) }}
{% elif env["netatalk_configured"] > 2 %}
{{ _("%(value)d active AFP connections", value=(env["netatalk_configured"] - 1)) }}
{% endif %}
</div>
<div>
{% if env["macproxy_configured"] %}
{{ _("Macproxy is running at %(ip_addr)s (default port 5000)", ip_addr=env['ip_addr']) }}
{% endif %}
</div>
<div>
{{ _("RaSCSI Reloaded version: ") }}<b>{{ env["version"] }} <a href="https://github.com/akuker/RASCSI/commit/{{ env["running_env"]["git"] }}" target="_blank">{{ env["running_env"]["git"][:7] }}</a></b>
</div>
<div>
{{ _("Pi environment: ") }}{{ env["running_env"]["env"] }}
</div>
</div>
</div>
</body>

View File

@ -1,52 +1,52 @@
{% extends "base.html" %}
{% block content %}
<h3>{{ _("Detailed Info for Attached Devices") }}</h3>
<h2>{{ _("Detailed Info for Attached Devices") }}</h2>
{% for device in devices %}
<p>
<table border="black" cellpadding="3">
<table border="black" cellpadding="3" summary="Detailed information for attached devices">
<tr>
<td><i>{{ _("SCSI ID") }}</i></td>
<th scope="row">{{ _("SCSI ID") }}</th>
<td>{{ device["id"] }}</td>
</tr>
<tr>
<td><i>{{ _("LUN") }}</i></td>
<th scope="row">{{ _("LUN") }}</th>
<td>{{ device["unit"] }}</td>
</tr>
<tr>
<td><i>{{ _("Type") }}</i></td>
<th scope="row">{{ _("Type") }}</th>
<td>{{ device["device_type"] }}</td>
</tr>
<tr>
<td><i>{{ _("Status") }}</i></td>
<th scope="row">{{ _("Status") }}</th>
<td>{{ device["status"] }}</td>
</tr>
<tr>
<td><i>{{ _("File") }}</i></td>
<th scope="row">{{ _("File") }}</th>
<td>{{ device["image"] }}</td>
</tr>
<tr>
<td><i>{{ _("Parameters") }}</i></td>
<th scope="row">{{ _("Parameters") }}</th>
<td>{{ device["params"] }}</td>
</tr>
<tr>
<td><i>{{ _("Vendor") }}</i></td>
<th scope="row">{{ _("Vendor") }}</th>
<td>{{ device["vendor"] }}</td>
</tr>
<tr>
<td><i>{{ _("Product") }}</i></td>
<th scope="row">{{ _("Product") }}</th>
<td>{{ device["product"] }}</td>
</tr>
<tr>
<td><i>{{ _("Revision") }}</i></td>
<th scope="row">{{ _("Revision") }}</th>
<td>{{ device["revision"] }}</td>
</tr>
<tr>
<td><i>{{ _("Block Size") }}</i></td>
<th scope="row">{{ _("Block Size") }}</th>
<td>{{ device["block_size"] }}</td>
</tr>
<tr>
<td><i>{{ _("Image Size") }}</i></td>
<th scope="row">{{ _("Image Size") }}</th>
<td>{{ device["size"] }}</td>
</tr>
</table>

View File

@ -1,7 +1,7 @@
{% extends "base.html" %}
{% block content %}
<h3>{{ _("Disk Image Details: %(file_name)s", file_name=file_name) }}</h3>
<h2>{{ _("Disk Image Details: %(file_name)s", file_name=file_name) }}</h2>
<p><pre>{{ diskinfo }}</pre></p>
<p><a href="/">{{ _("Go to Home") }}</a></p>

View File

@ -5,33 +5,32 @@
<p>{{ _("These device profiles are provided as-is with no guarantee to work equally to the actual physical device they are named after. You may need to provide appropirate device drivers and/or configuration parameters for them to function properly. If you would like to see data modified, or have additional devices to add to the list, please raise an issue ticket at <a href=\"%(url)s\">GitHub</a>.", url="https://github.com/akuker/RASCSI/issues") }}</p>
<h2>{{ _("Hard Disk Drives") }}</h2>
<table cellpadding="3" border="black">
<table cellpadding="3" border="black" summary="List of hard drives">
<tbody>
<tr>
<td><b>{{ _("Name") }}</b></td>
<td><b>{{ _("Size (MiB)") }}</b></td>
<td><b>{{ _("Description") }}</b></td>
<td><b>{{ _("Ref.") }}</b></td>
<td><b>{{ _("Action") }}</b></td>
<th scope="col">{{ _("Name") }}</th>
<th scope="col">{{ _("Size (MiB)") }}</th>
<th scope="col">{{ _("Description") }}</th>
<th scope="col">{{ _("Action") }}</th>
</tr>
{% for hd in drive_properties['hd_conf']|sort(attribute='name') %}
<tr>
<td style="text-align:center">{{ hd.name }}</td>
<td style="text-align:center">{{ hd.size_mb }}</td>
<td style="text-align:left">{{ hd.description }}</td>
<td style="text-align:left">
{% if hd.url != "" %}
<a href="{{ hd.url }}">{{ _("Link") }}</a>
{% else %}
-
{% endif %}
</td>
<td style="text-align:left">
<td align="center">
{% if hd.url != "" %}
<a href="{{ hd.url }}">{{ hd.name }}</a>
{% else %}
{{ hd.name }}
{% endif %}
</td>
<td align="center">{{ hd.size_mb }}</td>
<td>{{ hd.description }}</td>
<td>
<form action="/drive/create" method="post">
<input type="hidden" name="drive_name" value="{{ hd.name }}">
{{ _("Size:") }} <input type="number" name="size" min="512" max="274877906944" step="512" value="{{ hd.size }}">{{ _("B") }}
<label for="file_name">{{ _("Save as:") }}</label>
<input type="text" name="file_name" value="{{ hd.secure_name }}" required />.{{ hd.file_type }}
<label for="size_{{ hd.name }}">{{ _("Size:") }}</label>
<input type="number" name="size" id="size_{{ hd.name }}" min="512" max="274877906944" step="512" value="{{ hd.size }}">{{ _("B") }}
<label for="file_name_{{ hd.name }}">{{ _("Save as:") }}</label>
<input type="text" name="file_name" id="file_name_{{ hd.name }}" value="{{ hd.secure_name }}" required />.{{ hd.file_type }}
<input type="submit" value="{{ _("Create") }}" />
</form>
</td>
@ -44,38 +43,36 @@
<h2>{{ _("CD/DVD Drives") }}</h2>
<p><em>{{ _("This will create a properties file for the given CD-ROM or DVD image. No new image file will be created.") }}</em></p>
<table cellpadding="3" border="black">
<table cellpadding="3" border="black" summary="List of CD-ROM or DVD drives">
<tbody>
<tr>
<td><b>{{ _("Name") }}</b></td>
<td><b>{{ _("Size (MiB)") }}</b></td>
<td><b>{{ _("Description") }}</b></td>
<td><b>{{ _("Ref.") }}</b></td>
<td><b>{{ _("Action") }}</b></td>
<th scope="col">{{ _("Name") }}</th>
<th scope="col">{{ _("Size (MiB)") }}</th>
<th scope="col">{{ _("Description") }}</th>
<th scope="col">{{ _("Action") }}</th>
</tr>
{% for cd in drive_properties['cd_conf']|sort(attribute='name') %}
<tr>
<td style="text-align:center">{{ cd.name }}</td>
<td style="text-align:center">{{ cd.size_mb }}</td>
<td style="text-align:left">{{ cd.description }}</td>
<td style="text-align:left">
{% if cd.url != "" %}
<a href="{{ cd.url }}">{{ _("Link") }}</a>
{% else %}
-
{% endif %}
<td align="center">
{% if cd.url != "" %}
<a href="{{ cd.url }}">{{ cd.name }}</a>
{% else %}
{{ cd.name }}
{% endif %}
</td>
<td style="text-align:left">
<td align="center">{{ cd.size_mb }}</td>
<td>{{ cd.description }}</td>
<td>
<form action="/drive/cdrom" method="post">
<input type="hidden" name="drive_name" value="{{ cd.name }}">
<label for="file_name">{{ _("Create for:") }}</label>
<select type="select" name="file_name">
<label for="file_name_{{ cd.name }}">{{ _("Create for:") }}</label>
<select type="select" name="file_name" id="file_name_{{ cd.name }}">
{% for file in files|sort(attribute='name') %}
{% if file["name"].lower().endswith(cdrom_file_suffix) %}
<option value="{{ file["name"] }}">{{ file["name"].replace(base_dir, '') }}</option>
{% endif %}
{% endfor %}
</select>
{% if file["name"].lower().endswith(env['cd_suffixes']) %}
<option value="{{ file["name"] }}">{{ file["name"].replace(env["image_dir"], '') }}</option>
{% endif %}
{% endfor %}
</select>
<input type="submit" value="{{ _("Create") }}" />
</form>
</td>
@ -87,33 +84,32 @@
<hr/>
<h2>{{ _("Removable Disk Drives") }}</h2>
<table cellpadding="3" border="black">
<table cellpadding="3" border="black" summary="List of removable disk drives">
<tbody>
<tr>
<td><b>{{ _("Name") }}</b></td>
<td><b>{{ _("Size (MiB)") }}</b></td>
<td><b>{{ _("Description") }}</b></td>
<td><b>{{ _("Ref.") }}</b></td>
<td><b>{{ _("Action") }}</b></td>
<th scope="col">{{ _("Name") }}</th>
<th scope="col">{{ _("Size (MiB)") }}</th>
<th scope="col">{{ _("Description") }}</th>
<th scope="col">{{ _("Action") }}</th>
</tr>
{% for rm in drive_properties['rm_conf']|sort(attribute='name') %}
<tr>
<td style="text-align:center">{{ rm.name }}</td>
<td style="text-align:center">{{ rm.size_mb }}</td>
<td style="text-align:left">{{ rm.description }}</td>
<td style="text-align:left">
{% if rm.url != "" %}
<a href="{{ rm.url }}">{{ _("Link") }}</a>
{% else %}
-
{% endif %}
<td align="center">
{% if rm.url != "" %}
<a href="{{ rm.url }}">{{ rm.name }}</a>
{% else %}
{{ rm.name }}
{% endif %}
</td>
<td style="text-align:left">
<td align="center">{{ rm.size_mb }}</td>
<td>{{ rm.description }}</td>
<td>
<form action="/drive/create" method="post">
<input type="hidden" name="drive_name" value="{{ rm.name }}">
{{ _("Size:") }} <input type="number" name="size" min="512" max="274877906944" step="512" value="{{ rm.size }}">{{ _("B") }}
<label for="file_name">{{ _("Save as:") }}</label>
<input type="text" name="file_name" value="{{ rm.secure_name }}" required />.{{ rm.file_type }}
<label for="size_{{ rm.name }}">{{ _("Size:") }}</label>
<input type="number" name="size" id="size_{{ rm.name }}" min="512" max="274877906944" step="512" value="{{ rm.size }}">{{ _("B") }}
<label for="file_name_{{ rm.name }}">{{ _("Save as:") }}</label>
<input type="text" name="file_name" id="file_name_{{ rm.name }}" value="{{ rm.secure_name }}" required />.{{ rm.file_type }}
<input type="submit" value="{{ _("Create") }}" />
</form>
</td>

View File

@ -7,17 +7,19 @@
</summary>
<ul>
<li>{{ _("Displays the currently attached devices for each available SCSI ID.") }}</li>
<li>{{ _("Save and load device configurations, stored as json files in <tt>%(config_dir)s</tt>", config_dir=CFG_DIR) }}</tt></li>
<li>{{ _("Save and load device configurations, stored as json files in <tt>%(config_dir)s</tt>", config_dir=CFG_DIR) }}</li>
<li>{{ _("To have a particular device configuration load when RaSCSI starts, save it as <em>default</em>.") }}</li>
</ul>
</details>
<p><form action="/config/load" method="post">
<select name="name" required="" width="14">
<p>
<form action="/config/load" method="post">
<label for="config_load_name">{{ _("File name") }}</label>
<select name="name" id="config_load_name" required="" width="14">
{% if config_files %}
{% for config in config_files|sort %}
<option value="{{ config }}">
{{ config.replace(".json", '') }}
{{ config }}
</option>
{% endfor %}
{% else %}
@ -28,53 +30,59 @@
</select>
<input name="load" type="submit" value="{{ _("Load") }}" onclick="return confirm('{{ _("Detach all current device and Load configuration?") }}')">
<input name="delete" type="submit" value="{{ _("Delete") }}" onclick="return confirm('{{ _("Delete configuration file?") }}')">
</form></p>
</form>
</p>
<p><form action="/config/save" method="post">
<input name="name" placeholder="default" size="20">
<p>
<form action="/config/save" method="post">
<label for="config_save_name">{{ _("File name") }}</label>
<input name="name" id="config_save_name" placeholder="default" size="20">
.{{ CONFIG_FILE_SUFFIX }}
<input type="submit" value="{{ _("Save") }}">
</form></p>
</form>
</p>
<table border="black" cellpadding="3">
<table border="black" cellpadding="3" summary="List of attached devices">
<tbody>
<tr>
<td><b>{{ _("ID") }}</b></td>
<th scope="col">{{ _("ID") }}</th>
{% if units %}
<td><b>{{ _("LUN") }}</b></td>
<th scope="col">{{ _("LUN") }}</th>
{% endif %}
<td><b>{{ _("Device") }}</b></td>
<td><b>{{ _("Parameters") }}</b></td>
<td><b>{{ _("Product") }}</b></td>
<td><b>{{ _("Actions") }}</b></td>
<th scope="col">{{ _("Device") }}</th>
<th scope="col">{{ _("Parameters") }}</th>
<th scope="col">{{ _("Product") }}</th>
<th scope="col">{{ _("Actions") }}</th>
</tr>
{% for device in devices | sort(attribute='id') %}
<tr>
{% if device["id"] not in reserved_scsi_ids %}
<td style="text-align:center">{{ device.id }}</td>
<td align="center">{{ device.id }}</td>
{% if units %}
<td style="text-align:center">{{ device.unit }}</td>
<td align="center">{{ device.unit }}</td>
{% endif %}
<td style="text-align:center">{{ device.device_name }}</td>
<td style="text-align:left">
<td align="center">{{ device.device_name }}</td>
<td>
{% if "No Media" in device.status %}
<form action="/scsi/attach" method="post">
<input name="scsi_id" type="hidden" value="{{ device.id }}">
<input name="unit" type="hidden" value="{{ device.unit }}">
<input name="type" type="hidden" value="{{ device.device_type }}">
<input name="file_size" type="hidden" value="{{ device.size }}">
<select type="select" name="file_name">
<label for="device_list_file_name_{{ device.id }}_{{ device.unit }}">{{ _("File name") }}</label>
<select type="select" name="file_name" id="device_list_file_name_{{ device.id }}_{{ device.unit }}">
{% for f in files|sort(attribute='name') %}
{% if device.device_type == "SCCD" %}
{% if f["name"].lower().endswith(cdrom_file_suffix) %}
<option value="{{ f["name"] }}">{{ f["name"].replace(base_dir, '') }}</option>
{% if f["name"].lower().endswith(env['cd_suffixes']) %}
<option value="{{ f["name"] }}">{{ f["name"].replace(env["image_dir"], '') }}</option>
{% endif %}
{% elif device.device_type == "SCRM" %}
{% if f["name"].lower().endswith(removable_file_suffix) %}
<option value="{{ f["name"] }}">{{ f["name"].replace(base_dir, '') }}</option>
{% if f["name"].lower().endswith(env['rm_suffixes']) %}
<option value="{{ f["name"] }}">{{ f["name"].replace(env["image_dir"], '') }}</option>
{% endif %}
{% elif device.device_type == "SCMO" %}
{% if f["name"].lower().endswith(mo_file_suffix) %}
<option value="{{ f["name"] }}">{{ f["name"].replace(base_dir, '') }}</option>
{% if f["name"].lower().endswith(env['mo_suffixes']) %}
<option value="{{ f["name"] }}">{{ f["name"].replace(env["image_dir"], '') }}</option>
{% endif %}
{% endif %}
{% endfor %}
@ -97,7 +105,7 @@
{% endif %}
{% endif %}
</td>
<td style="text-align:center">
<td align="center">
{% if device.vendor != "RaSCSI" %}
{{ device.vendor }}
{% endif %}
@ -106,8 +114,8 @@
{{ device.revision }}
{% endif %}
</td>
<td style="text-align:center">
{% if device.id in scsi_ids["occupied_ids"] %}
<td align="center">
{% if device.id in scsi_ids["occupied_ids"] %}
{% if device.device_type in REMOVABLE_DEVICE_TYPES and "No Media" not in device.status %}
<form action="/scsi/eject" method="post" onsubmit="return confirm('{{ _("Eject Disk? WARNING: On Mac OS, eject the Disk in the Finder instead!") }}')">
<input name="scsi_id" type="hidden" value="{{ device.id }}">
@ -120,13 +128,13 @@
<input name="unit" type="hidden" value="{{ device.unit }}">
<input type="submit" value="{{ _("Detach") }}">
</form>
{% else %}
<form action="/scsi/reserve" method="post" onsubmit="var memo = prompt('{{ _("Enter a memo for this reservation") }}'); if (memo === null) event.preventDefault(); document.getElementById('memo_{{ device.id }}').value = memo;">
{% else %}
<form action="/scsi/reserve" method="post" onsubmit="var memo = prompt('{{ _("Enter a memo for this reservation") }}'); if (memo === null) event.preventDefault(); document.getElementById('memo_{{ device.id }}').value = memo;">
<input name="scsi_id" type="hidden" value="{{ device.id }}">
<input name="memo" id="memo_{{ device.id }}" type="hidden" value="">
<input type="submit" value="{{ _("Reserve") }}">
</form>
{% endif %}
{% endif %}
</td>
{% else %}
<td class="inactive">{{ device.id }}</td>
@ -148,20 +156,14 @@
</tbody>
</table>
<table style="border: none;" cellpadding="3">
<tr style="border: none;">
<td style="border: none;">
<form action="/scsi/detach_all" method="post" onsubmit="return confirm('{{ _("Detach all SCSI Devices?") }}')">
<input type="submit" value="{{ _("Detach All Devices") }}">
</form>
</td>
<td style="border: none;">
<form action="/scsi/info" method="post">
<input type="submit" value="{{ _("Show Device Info") }}">
</form>
</td>
</tr>
</table>
<p>
<form action="/scsi/detach_all" method="post" onsubmit="return confirm('{{ _("Detach all SCSI Devices?") }}')">
<input type="submit" value="{{ _("Detach All Devices") }}">
</form>
<form action="/scsi/info" method="post">
<input type="submit" value="{{ _("Show Device Info") }}">
</form>
</p>
<hr/>
@ -170,7 +172,7 @@
{{ _("Image File Management") }}
</summary>
<ul>
<li>{{ _("Manage image files in the active RaSCSI image directory: <tt>%(directory)s</tt> with a scan depth of %(scan_depth)s.", directory=base_dir, scan_depth=scan_depth) }}</li>
<li>{{ _("Manage image files in the active RaSCSI image directory: <tt>%(directory)s</tt> with a scan depth of %(scan_depth)s.", directory=env["image_dir"], scan_depth=scan_depth) }}</li>
<li>{{ _("Select a valid SCSI ID and <a href=\"%(url)s\" target=\"_blank\">LUN</a> to attach to. Unless you know what you're doing, always use LUN 0.", url="https://en.wikipedia.org/wiki/Logical_unit_number") }}
</li>
<li>{{ _("If RaSCSI was unable to detect the media type associated with the image, you get to choose the type from the dropdown.") }}</li>
@ -187,12 +189,12 @@
</ul>
</details>
<table border="black" cellpadding="3">
<table border="black" cellpadding="3" summary="List of files in the image directory">
<tbody>
<tr style="font-weight: bold;">
<td>{{ _("File") }}</td>
<td>{{ _("Size") }}</td>
<td>{{ _("Actions") }}</td>
<tr>
<th scope="col">{{ _("File") }}</th>
<th scope="col">{{ _("Size") }}</th>
<th scope="col">{{ _("Actions") }}</th>
</tr>
{% for file in files|sort(attribute='name') %}
<tr>
@ -202,12 +204,12 @@
<summary>
{{ file["name"] }}
</summary>
<ul style="list-style: none;">
<ul class="inline_list">
{% for key in file["prop"] %}
<li>{{ key }}: {{ file['prop'][key] }}</li>
{% endfor %}
<form action="/files/download" method="post">
<input name="file" type="hidden" value="{{ CFG_DIR }}/{{ file['name'].replace(base_dir, '') }}.{{ PROPERTIES_SUFFIX }}">
<input name="file" type="hidden" value="{{ CFG_DIR }}/{{ file['name'].replace(env['image_dir'], '') }}.{{ PROPERTIES_SUFFIX }}">
<input type="submit" value="{{ _("Properties File") }} &#8595;">
</form>
</ul>
@ -219,7 +221,7 @@
<summary>
{{ file["name"] }}
</summary>
<ul style="list-style: none;">
<ul class="inline_list">
{% for member in file["archive_contents"] %}
{% if not member["is_properties_file"] %}
<li>
@ -233,7 +235,7 @@
<input type="submit" value="{{ _("Extract") }}" onclick="processNotify('{{ _("Extracting a single file...") }}')">
</form>
</summary>
<ul style="list-style: none;">
<ul class="inline_list">
<li>{{ member["related_properties_file"] }}</li>
</ul>
</details>
@ -254,9 +256,9 @@
{% else %}
<td>{{ file["name"] }}</td>
{% endif %}
<td style="text-align:center">
<td align="center">
<form action="/files/download" method="post">
<input name="file" type="hidden" value="{{ base_dir }}/{{ file['name'] }}">
<input name="file" type="hidden" value="{{ env["image_dir"] }}/{{ file['name'] }}">
<input type="submit" value="{{ file['size_mb'] }} {{ _("MiB") }} &#8595;">
</form>
</td>
@ -275,23 +277,24 @@
<form action="/scsi/attach" method="post">
<input name="file_name" type="hidden" value="{{ file['name'] }}">
<input name="file_size" type="hidden" value="{{ file['size'] }}">
<label for="id">{{ _("ID") }}</label>
<select name="scsi_id">
<label for="image_list_scsi_id_{{ file["name"] }}">{{ _("ID") }}</label>
<select name="scsi_id" id="image_list_scsi_id_{{ file["name"] }}">
{% for id in scsi_ids["valid_ids"] %}
<option name="id" value="{{id}}"{% if id == scsi_ids["recommended_id"] %} selected{% endif %}>
{{ id }}
</option>
{% endfor %}
</select>
<label for="unit">{{ _("LUN") }}</label>
<input name="unit" type="number" value="0" min="0" max="31" step="1">
<label for="image_list_unit_{{ file["name"] }}">{{ _("LUN") }}</label>
<input class="lun" name="unit" id="image_list_unit_{{ file["name"] }}" type="number" value="0" min="0" max="31" step="1" size="3">
{% if file["detected_type"] != "UNDEFINED" %}
<input name="type" type="hidden" value="{{ file['detected_type'] }}">
{{ file['detected_type_name'] }}
{% else %}
<select name="type">
<label for="image_list_type_{{ file["name"] }}">{{ _("Type") }}</label>
<select name="type" id="image_list_type_{{ file["name"] }}">
<option selected disabled value="">
{{ _("Select media type") }}
{{ _("Unknown") }}
</option>
{% for key, value in device_types.items() %}
{% if key in DISK_DEVICE_TYPES %}
@ -344,7 +347,7 @@
<ul>
{% if bridge_configured %}
<li>{{ _("The <tt>rascsi_bridge</tt> network bridge is active and ready to be used by an emulated network adapter!") }}</li>
{% else %}
{% else %}
<li>{{ _("Please configure the <tt>rascsi_bridge</tt> network bridge before attaching an emulated network adapter!") }}</li>
{% endif %}
<li>{{ _("If you have a DHCP setup, choose only the interface you have configured the bridge with. You can ignore the inet field when attaching.") }}</li>
@ -355,11 +358,11 @@
</li>
</ul>
</details>
<table border="black" cellpadding="3">
<tr style="font-weight: bold;">
<td>{{ _("Device") }}</td>
<td>{{ _("Key") }}</td>
<td>{{ _("Parameters and Actions") }}</td>
<table border="black" cellpadding="3" summary="List of peripheral devices">
<tr>
<th scope="col">{{ _("Device") }}</th>
<th scope="col">{{ _("Key") }}</th>
<th scope="col">{{ _("Parameters and Actions") }}</th>
</tr>
{% for type in REMOVABLE_DEVICE_TYPES + PERIPHERAL_DEVICE_TYPES %}
<tr>
@ -373,11 +376,11 @@
<form action="/scsi/attach_device" method="post">
<input name="type" type="hidden" value="{{ type }}">
{% for key, value in device_types[type]["params"] | dictsort %}
<label for="param_{{ key }}">{{ key }}:</label>
<label for="param_{{ type }}_{{ key }}">{{ key }}:</label>
{% if value.isnumeric() %}
<input name="param_{{ key }}" id="param_{{ key }}" type="number" value="{{ value }}">
<input name="param_{{ key }}" id="param_{{ type }}_{{ key }}" type="number" value="{{ value }}">
{% elif key == "interface" %}
<select name="param_{{ key }}" id="param_{{ key }}">
<select name="param_{{ key }}" id="param_{{ type }}_{{ key }}">
{% for if in netinfo["ifs"] %}
<option value="{{ if }}">
{{ if }}
@ -385,12 +388,12 @@
{% endfor %}
</select>
{% else %}
<input name="param_{{ key }}" id="param_{{ key }}" type="text" size="{{ value|length }}" placeholder="{{ value }}">
<input name="param_{{ key }}" id="param_{{ type }}_{{ key }}" type="text" size="{{ value|length }}" placeholder="{{ value }}">
{% endif %}
{% endfor %}
{% if type in REMOVABLE_DEVICE_TYPES %}
<label for="drive_name">{{ _("Masquerade as:") }}</label>
<select name="drive_name">
<label for="{{ type }}_drive_name">{{ _("Masquerade as:") }}</label>
<select name="drive_name" id="{{ type }}_drive_name">
<option value="">
{{ _("None") }}
</option>
@ -417,16 +420,16 @@
{% endif %}
</select>
{% endif %}
<label for="scsi_id">{{ _("SCSI ID:") }}</label>
<select name="scsi_id">
<label for="{{ type }}_scsi_id">{{ _("ID") }}</label>
<select name="scsi_id" id="{{ type }}_scsi_id">
{% for id in scsi_ids["valid_ids"] %}
<option value="{{ id }}"{% if id == scsi_ids["recommended_id"] %} selected{% endif %}>
{{ id }}
</option>
{% endfor %}
</select>
<label for="unit">{{ _("LUN") }}</label>
<input name="unit" type="number" value="0" min="0" max="31" step="1">
<label for="{{ type }}_unit">{{ _("LUN") }}</label>
<input class="lun" name="unit" id="{{ type }}_unit" type="number" value="0" min="0" max="31" step="1" size="3">
<input type="submit" value="{{ _("Attach") }}">
</form>
</td>
@ -446,21 +449,16 @@
</ul>
</details>
<table style="border: none;">
<tr style="border: none;">
<td style="border: none; vertical-align:top;">
<form name="dropper" action="/files/upload" method="post" class="dropzone dz-clickable" enctype="multipart/form-data" id="dropper">
<p>
<label for="destination">{{ _("Target directory:") }}</label>
<select name="destination">
<option value="images">{{ base_dir }}</option>
<option value="afp">{{ AFP_DIR }}</option>
</select>
</p>
</form>
</td>
</tr>
</table>
<form name="dropper" action="/files/upload" method="post" class="dropzone dz-clickable" enctype="multipart/form-data" id="dropper">
<p>
<label for="upload_destination">{{ _("Target directory:") }}</label>
<select name="destination" id="upload_destination">
<option value="images">{{ env["image_dir"] }}</option>
<option value="afp">{{ AFP_DIR }}</option>
</select>
</p>
</form>
<script type="application/javascript">
Dropzone.options.dropper = {
paramName: 'file',
@ -502,22 +500,16 @@
</ul>
</details>
<table style="border: none">
<tr style="border: none">
<td style="border: none; vertical-align:top;">
<form action="/files/download_url" method="post">
<label for="destination">{{ _("Target directory:") }}</label>
<select name="destination">
<option value="images">{{ base_dir }}</option>
<option value="afp">{{ AFP_DIR }}</option>
</select>
<label for="url">{{ _("URL:") }}</label>
<input name="url" placeholder="{{ _("URL") }}" required="" type="url">
<input type="submit" value="{{ _("Download") }}" onclick="processNotify('{{ _("Downloading File...") }}')">
</form>
</td>
</tr>
</table>
<form action="/files/download_url" method="post">
<label for="download_destination">{{ _("Target directory:") }}</label>
<select name="destination" id="download_destination">
<option value="images">{{ env["image_dir"] }}</option>
<option value="afp">{{ AFP_DIR }}</option>
</select>
<label for="download_url">{{ _("URL:") }}</label>
<input name="url" id="download_url" required="" type="url">
<input type="submit" value="{{ _("Download") }}" onclick="processNotify('{{ _("Downloading File...") }}')">
</form>
<hr/>
@ -531,46 +523,41 @@
<li>{{ _("If the downloaded file is a zip archive, we will attempt to unzip it and store the resulting files.") }}</li>
</ul>
</details>
<table style="border: none">
<tr style="border: none">
<td style="border: none; vertical-align:top;">
<label for="scsi_id">{{ _("SCSI ID:") }}</label>
<form action="/files/download_to_iso" method="post">
<select name="scsi_id">
{% for id in scsi_ids["valid_ids"] %}
<option value="{{ id }}"{% if id == scsi_ids["recommended_id"] %} selected{% endif %}>
{{ id }}
</option>
{% endfor %}
</select>
<label for="url">{{ _("URL:") }}</label>
<input name="url" placeholder="{{ _("URL") }}" required="" type="url">
<label for="type">{{ _("Type:") }}</label>
<select name="type">
<option value="-hfs">
HFS
</option>
<option value="-iso-level 1">
ISO-9660 Level 1
</option>
<option value="-iso-level 2">
ISO-9660 Level 2
</option>
<option value="-iso-level 3">
ISO-9660 Level 3
</option>
<option value="-J">
Joliet
</option>
<option value="-r">
Rock Ridge
</option>
</select>
<input type="submit" value="{{ _("Download and Mount CD-ROM image") }}" onclick="processNotify('{{ _("Downloading File and generating CD-ROM image...") }}')">
</form>
</td>
</tr>
</table>
<form action="/files/download_to_iso" method="post">
<label for="iso_url">{{ _("URL:") }}</label>
<input name="url" id="iso_url" required="" type="url">
<label for="iso_type">{{ _("Type:") }}</label>
<select name="type" id="iso_type">
<option value="-hfs">
HFS
</option>
<option value="-iso-level 1">
ISO-9660 Level 1
</option>
<option value="-iso-level 2">
ISO-9660 Level 2
</option>
<option value="-iso-level 3">
ISO-9660 Level 3
</option>
<option value="-J">
Joliet
</option>
<option value="-r">
Rock Ridge
</option>
</select>
<label for="iso_scsi_id">{{ _("ID") }}</label>
<select name="scsi_id" id="iso_scsi_id">
{% for id in scsi_ids["valid_ids"] %}
<option value="{{ id }}"{% if id == scsi_ids["recommended_id"] %} selected{% endif %}>
{{ id }}
</option>
{% endfor %}
</select>
<input type="submit" value="{{ _("Download and Mount CD-ROM image") }}" onclick="processNotify('{{ _("Downloading File and generating CD-ROM image...") }}')">
</form>
<hr/>
@ -582,38 +569,33 @@
<li>{{ _("Please refer to <a href=\"%(url)s\" target=\"_blank\">wiki documentation</a> to learn more about the supported image file types.", url="https://github.com/akuker/RASCSI/wiki/Supported-Device-Types#image-types") }}</li>
</ul>
</details>
<table style="border: none">
<tr style="border: none">
<td style="border: none; vertical-align:top;">
<form action="/files/create" method="post">
<label for="file_name">{{ _("File Name:") }}</label>
<input name="file_name" placeholder="{{ _("File Name") }}" required="" type="text">
<label for="type">{{ _("Type:") }}</label>
<select name="type">
{% for key, value in image_suffixes_to_create.items() %}
<option value="{{ key }}">
{{ value }} [.{{ key }}]
</option>
{% endfor %}
</select>
<label for="size">{{ _("Size:") }}</label>
<input name="size" type="number" placeholder="{{ _("MiB") }}" min="1" max="262144" required>
<label for="drive_name">{{ _("Masquerade as:") }}</label>
<select name="drive_name">
<option value="">
{{ _("None") }}
</option>
{% for drive in drive_properties["hd_conf"] | sort(attribute='name') %}
<option value="{{ drive.name }}">
{{ drive.name }}
</option>
{% endfor %}
</select>
<input type="submit" value="{{ _("Create") }}">
</form>
</td>
</tr>
</table>
<form action="/files/create" method="post">
<label for="image_create_file_name">{{ _("File Name:") }}</label>
<input name="file_name" id="image_create_file_name" required="" type="text">
<label for="image_create_type">{{ _("Type:") }}</label>
<select name="type" id="image_create_type">
{% for key, value in image_suffixes_to_create.items() %}
<option value="{{ key }}">
{{ value }} [.{{ key }}]
</option>
{% endfor %}
</select>
<label for="image_create_size">{{ _("Size:") }}</label>
<input name="size" id="image_create_size" type="number" placeholder="{{ _("MiB") }}" min="1" max="262144" required>
<label for="image_create_drive_name">{{ _("Masquerade as:") }}</label>
<select name="drive_name" id="image_create_drive_name">
<option value="">
{{ _("None") }}
</option>
{% for drive in drive_properties["hd_conf"] | sort(attribute='name') %}
<option value="{{ drive.name }}">
{{ drive.name }}
</option>
{% endfor %}
</select>
<input type="submit" value="{{ _("Create") }}">
</form>
<hr/>
@ -638,35 +620,30 @@
<li>{{ _("Fetch a certain number of lines of system logs with the given scope.") }}</li>
</ul>
</details>
<table style="border: none">
<tr style="border: none">
<td style="border: none; vertical-align:top;">
<form action="/logs/show" method="post">
<label for="lines">{{ _("Log Lines:") }}</label>
<input name="lines" type="number" value="200" min="0" max="99999" step="100">
<label for="scope">{{ _("Scope:") }}</label>
<select name="scope">
<option value="">
{{ _("All logs") }}
</option>
<option value="rascsi">
rascsi
</option>
<option value="rascsi-web">
rascsi-web
</option>
<option value="rascsi-oled">
rascsi-oled
</option>
<option value="rascsi-ctrlboard">
rascsi-ctrlboard
</option>
</select>
<input type="submit" value="{{ _("Show Logs") }}">
</form>
</td>
</tr>
</table>
<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="rascsi">
rascsi
</option>
<option value="rascsi-web">
rascsi-web
</option>
<option value="rascsi-oled">
rascsi-oled
</option>
<option value="rascsi-ctrlboard">
rascsi-ctrlboard
</option>
</select>
<input type="submit" value="{{ _("Show Logs") }}">
</form>
<hr/>
@ -679,23 +656,18 @@
<li>{{ _("The current dropdown selection indicates the active log level.") }}</li>
</ul>
</details>
<table style="border: none">
<tr style="border: none">
<td style="border: none; vertical-align:top;">
<form action="/logs/level" method="post">
<label for="level">{{ _("Log Level:") }}</label>
<select name="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>
</td>
</tr>
</table>
<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>
<hr/>
@ -707,23 +679,18 @@
<li>{{ _("Change the Web Interface language.") }}</li>
</ul>
</details>
<table style="border: none">
<tr style="border: none">
<td style="border: none; vertical-align:top;">
<form action="/language" method="post">
<label for="language">{{ _("Language:") }}</label>
<select name="locale">
{% for locale in locales %}
<option value="{{ locale.language }}">
{{ locale.language }} - {{ locale.display_name }}
</option>
{% endfor %}
</select>
<input type="submit" value="{{ _("Change Language") }}">
</form>
</td>
</tr>
</table>
<form action="/language" method="post">
<label for="locale">{{ _("Language:") }}</label>
<select name="locale" id="locale">
{% for locale in locales %}
<option value="{{ locale.language }}">
{{ locale.language }} - {{ locale.display_name }}
</option>
{% endfor %}
</select>
<input type="submit" value="{{ _("Change Language") }}">
</form>
<hr/>
@ -736,39 +703,16 @@
<li>{{ _("IMPORTANT: Always shut down the Pi before turning off the power. Failing to do so may lead to data loss.") }}</li>
</ul>
</details>
<table style="border: none">
<tr style="border: none">
<td style="border: none; vertical-align:top;">
<form action="/pi/reboot" method="post" onclick="if (confirm('{{ _("Reboot the Raspberry Pi?") }}')) shutdownNotify('{{ _("Rebooting the Raspberry Pi...") }}'); else event.preventDefault();">
<input type="submit" value="{{ _("Reboot Raspberry Pi") }}">
</form>
</td>
<td style="border: none; vertical-align:top;">
<form action="/pi/shutdown" method="post" onclick="if (confirm('{{ _("Shut down the Raspberry Pi?") }}')) shutdownNotify('{{ _("Shutting down the Raspberry Pi...") }}'); else event.preventDefault();">
<input type="submit" value="{{ _("Shut Down Raspberry Pi") }}">
</form>
</td>
</tr>
</table>
<form action="/pi/reboot" method="post" onclick="if (confirm('{{ _("Reboot the Raspberry Pi?") }}')) shutdownNotify('{{ _("Rebooting the Raspberry Pi...") }}'); else event.preventDefault();">
<input type="submit" value="{{ _("Reboot Raspberry Pi") }}">
</form>
<form action="/pi/shutdown" method="post" onclick="if (confirm('{{ _("Shut down the Raspberry Pi?") }}')) shutdownNotify('{{ _("Shutting down the Raspberry Pi...") }}'); else event.preventDefault();">
<input type="submit" value="{{ _("Shut Down Raspberry Pi") }}">
</form>
<hr/>
<a href="/sys/manpage?app=rascsi"><p>{{ _("Read the RaSCSI Manual") }}</p></a>
<center><tt>
{% if netatalk_configured == 1 %}
{{ _("The AppleShare server is running. No active connections.") }}
{% endif %}
{% if netatalk_configured == 2 %}
{{ _("%(value)d active AFP connection", value=(netatalk_configured - 1)) }}
{% elif netatalk_configured > 2 %}
{{ _("%(value)d active AFP connections", value=(netatalk_configured - 1)) }}
{% endif %}
</center></tt>
<center><tt>
{% if macproxy_configured %}
<center><tt>{{ _("Macproxy is running at %(ip_addr)s (default port 5000)", ip_addr=env['ip_addr']) }}</tt></center>
{% endif %}
</center></tt>
{% endblock content %}

View File

@ -1,7 +1,7 @@
{% extends "base.html" %}
{% block content %}
<h3>{{ _("System Logs: %(scope)s %(lines)s lines", scope=scope, lines=lines) }}</h3>
<h2>{{ _("System Logs: %(scope)s %(lines)s lines", scope=scope, lines=lines) }}</h2>
<p><pre>{{ logs }}</pre></p>
<p><a href="/">{{ _("Go to Home") }}</a></p>

View File

@ -1,7 +1,7 @@
{% extends "base.html" %}
{% block content %}
<h1>{{ _("Manual for %(app)s:", app=app) }}</h1>
<h2>{{ _("Manual for %(app)s", app=app) }}</h2>
{{ manpage | safe }}
<p><a href="/">{{ _("Go to Home") }}</a></p>

View File

@ -75,6 +75,7 @@ def get_env_info():
"""
Get information about the app/host environment
"""
server_info = ractl_cmd.get_server_info()
ip_addr, host = sys_cmd.get_ip_and_host()
if "username" in session:
@ -89,6 +90,14 @@ def get_env_info():
"ip_addr": ip_addr,
"host": host,
"free_disk_space": int(sys_cmd.disk_space()["free"] / 1024 / 1024),
"locale": get_locale(),
"version": server_info["version"],
"image_dir": server_info["image_dir"],
"netatalk_configured": sys_cmd.running_proc("afpd"),
"macproxy_configured": sys_cmd.running_proc("macproxy"),
"cd_suffixes": tuple(server_info["sccd"]),
"rm_suffixes": tuple(server_info["scrm"]),
"mo_suffixes": tuple(server_info["scmo"]),
}
@ -233,35 +242,29 @@ def index():
return response(
template="index.html",
locales=get_supported_locales(),
netinfo=ractl_cmd.get_network_info(),
bridge_configured=sys_cmd.is_bridge_setup(),
netatalk_configured=sys_cmd.running_proc("afpd"),
macproxy_configured=sys_cmd.running_proc("macproxy"),
devices=formatted_devices,
attached_images=attached_images,
files=extended_image_files,
config_files=config_files,
base_dir=server_info["image_dir"],
device_types=device_types,
scan_depth=server_info["scan_depth"],
CFG_DIR=CFG_DIR,
AFP_DIR=AFP_DIR,
scsi_ids=scsi_ids,
attached_images=attached_images,
units=units,
reserved_scsi_ids=reserved_scsi_ids,
RESERVATIONS=RESERVATIONS,
max_file_size=int(int(MAX_FILE_SIZE) / 1024 / 1024),
version=server_info["version"],
log_levels=server_info["log_levels"],
current_log_level=server_info["current_log_level"],
netinfo=ractl_cmd.get_network_info(),
device_types=device_types,
scsi_ids=scsi_ids,
units=units,
reserved_scsi_ids=reserved_scsi_ids,
image_suffixes_to_create=image_suffixes_to_create,
valid_image_suffixes=valid_image_suffixes,
cdrom_file_suffix=tuple(server_info["sccd"]),
removable_file_suffix=tuple(server_info["scrm"]),
mo_file_suffix=tuple(server_info["scmo"]),
drive_properties=drive_properties,
max_file_size=int(int(MAX_FILE_SIZE) / 1024 / 1024),
RESERVATIONS=RESERVATIONS,
CFG_DIR=CFG_DIR,
AFP_DIR=AFP_DIR,
PROPERTIES_SUFFIX=PROPERTIES_SUFFIX,
ARCHIVE_FILE_SUFFIXES=ARCHIVE_FILE_SUFFIXES,
CONFIG_FILE_SUFFIX=CONFIG_FILE_SUFFIX,
REMOVABLE_DEVICE_TYPES=ractl_cmd.get_removable_device_types(),
DISK_DEVICE_TYPES=ractl_cmd.get_disk_device_types(),
PERIPHERAL_DEVICE_TYPES=ractl_cmd.get_peripheral_device_types(),
@ -291,15 +294,10 @@ def drive_list():
"mo_conf": [],
}
server_info = ractl_cmd.get_server_info()
return response(
template="drives.html",
files=file_cmd.list_images()["files"],
base_dir=server_info["image_dir"],
drive_properties=drive_properties,
version=server_info["version"],
cdrom_file_suffix=tuple(server_info["sccd"]),
)
@ -469,7 +467,6 @@ def show_diskinfo():
template="diskinfo.html",
file_name=file_name,
diskinfo=diskinfo,
version=server_info["version"],
)
return response(
@ -493,7 +490,6 @@ def show_manpage():
message=_("%(app)s is not a recognized RaSCSI app", app=app)
)
server_info = ractl_cmd.get_server_info()
file_path = f"{WEB_DIR}/../../../doc/{app}.1"
html_to_strip = [
"Content-type",
@ -521,7 +517,6 @@ def show_manpage():
template="manpage.html",
app=app,
manpage=formatted_manpage,
version=server_info["version"],
)
return response(
@ -540,13 +535,11 @@ def show_logs():
returncode, logs = sys_cmd.get_logs(lines, scope)
if returncode == 0:
server_info = ractl_cmd.get_server_info()
return response(
template="logs.html",
scope=scope,
lines=lines,
logs=logs,
version=server_info["version"],
)
return response(
@ -764,13 +757,11 @@ def device_info():
"""
Displays detailed info for all attached devices
"""
server_info = ractl_cmd.get_server_info()
process = ractl_cmd.list_devices()
if process["status"]:
return response(
template="deviceinfo.html",
devices=process["device_list"],
version=server_info["version"],
)
return response(error=True, message=_("No devices attached"))