RASCSI/src/web/templates/index.html

647 lines
27 KiB
HTML

{% extends "base.html" %}
{% block content %}
<details>
<summary class="heading">
Current RaSCSI Configuration
</summary>
<ul>
<li>Displays the currently attached devices for each available SCSI ID.</li>
<li>Save and load device configurations into <tt>{{ CFG_DIR }}</tt></li>
<li>The <em>default</em> configuration will be loaded when the Web UI starts up, if available.</li>
</ul>
</details>
<p><form action="/config/load" method="post">
<select name="name" required="" width="14">
{% if config_files %}
{% for config in config_files %}
<option value="{{ config }}">
{{ config.replace(".json", '') }}
</option>
{% endfor %}
{% else %}
<option disabled>
No saved configs
</option>
{% endif %}
</select>
<input name="load" type="submit" value="Load" onclick="return confirm('Detach all current device and Load config?')">
<input name="delete" type="submit" value="Delete" onclick="return confirm('Delete config file?')">
</form></p>
<p><form action="/config/save" method="post">
<input name="name" placeholder="default" size="20">
<input type="submit" value="Save">
</form></p>
<table border="black" cellpadding="3">
<tbody>
<tr>
<td><b>ID</b></td>
{% if units %}
<td><b>LUN</b></td>
{% endif %}
<td><b>Type</b></td>
<td><b>Status</b></td>
<td><b>File</b></td>
<td><b>Product</b></td>
<td><b>Actions</b></td>
</tr>
{% for device in devices %}
<tr>
{% if device["id"] not in reserved_scsi_ids %}
<td style="text-align:center">{{ device.id }}</td>
{% if units %}
<td style="text-align:center">{{ device.unit }}</td>
{% endif %}
<td style="text-align:center">{{ device.device_type }}</td>
<td style="text-align:center">{{ device.status }}</td>
<td style="text-align:left">
{% 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">
{% for f in files %}
{% if device.device_type == "SCCD" %}
{% if f["name"].lower().endswith(cdrom_file_suffix) %}
<option value="{{ f["name"] }}">{{ f["name"].replace(base_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>
{% endif %}
{% elif device.device_type == "SCMO" %}
{% if f["name"].lower().endswith(mo_file_suffix) %}
<option value="{{ f["name"] }}">{{ f["name"].replace(base_dir, '') }}</option>
{% endif %}
{% endif %}
{% endfor %}
</select>
<input type="submit" value="Attach">
</form>
{% else %}
{{ device.file }}
</td>
{% endif %}
{% if device.vendor == "RaSCSI" %}
<td style="text-align:center">{{ device.product }}</td>
{% else %}
<td style="text-align:center">{{ device.vendor }} {{ device.product }}</td>
{% endif %}
<td style="text-align:center">
{% if device.device_type != "-" %}
{% 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 Finder instead!')">
<input name="scsi_id" type="hidden" value="{{ device.id }}">
<input name="unit" type="hidden" value="{{ device.unit }}">
<input type="submit" value="Eject">
</form>
{% else %}
<form action="/scsi/detach" method="post" onsubmit="return confirm('Detach Device?')">
<input name="scsi_id" type="hidden" value="{{ device.id }}">
<input name="unit" type="hidden" value="{{ device.unit }}">
<input type="submit" value="Detach">
</form>
{% endif %}
<form action="/scsi/info" method="post">
<input name="scsi_id" type="hidden" value="{{ device.id }}">
<input name="unit" type="hidden" value="{{ device.unit }}">
<input type="submit" value="Info">
</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;">
<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 %}
</td>
{% else %}
<td class="inactive">{{ device.id }}</td>
{% if units %}
<td class="inactive"></td>
{% endif %}
<td class="inactive"></td>
<td class="inactive">Reserved ID</td>
<td class="inactive">{{ RESERVATIONS[device.id] }}</td>
<td class="inactive"></td>
<td class="inactive">
<form action="/scsi/unreserve" method="post">
<input name="scsi_id" type="hidden" value="{{ device.id }}">
<input type="submit" value="Unreserve">
</form>
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
<p><form action="/scsi/detach_all" method="post" onsubmit="return confirm('Detach all SCSI Devices?')">
<input type="submit" value="Detach All Devices">
</form></p>
<hr/>
<details>
<summary class="heading">
Image File Management
</summary>
<ul>
<li>Manage image files in the active RaSCSI image directory: <tt>{{ base_dir }}</tt></li>
<li>Select a valid SCSI ID and <a href="https://en.wikipedia.org/wiki/Logical_unit_number">LUN</a> to attach to. Unless you know what you're doing, always use LUN 0.
</li>
<li>If RaSCSI was unable to detect the device type associated with the image, you can choose the type from the dropdown.</li>
<li>Types: SAHD = SASI HDD | SCHD = SCSI HDD | SCRM = Removable | SCMO = Magneto-Optical | SCCD = CD-ROM | SCBR = Host Bridge | SCDP = DaynaPORT</li>
</ul>
</details>
<table border="black" cellpadding="3">
<tbody>
<tr>
<td><b>File</b></td>
<td><b>Size</b></td>
<td><b>Actions</b></td>
</tr>
{% for file in files %}
<tr>
{% if file["prop"] %}
<td>
<details>
<summary>
{{ file["name"] }}
</summary>
<ul style="list-style: none;">
{% 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 type="submit" value="Properties File &#8595;">
</form>
</ul>
</details>
</td>
{% elif file["zip_members"] %}
<td>
<details>
<summary>
{{ file["name"] }}
</summary>
<ul style="list-style: none;">
{% for member in file["zip_members"] %}
{% if not member.lower().endswith(PROPERTIES_SUFFIX) %}
<li>
{% if member + "." + PROPERTIES_SUFFIX in file["zip_members"] %}
<details><summary>{{ member }}
<form action="/files/unzip" method="post">
<input name="zip_file" type="hidden" value="{{ file['name'] }}">
<input name="zip_member" type="hidden" value="{{ member }}">
<input type="submit" value="Unzip" onclick="processNotify('Unzipping a single file...')">
</form>
</summary>
<ul style="list-style: none;">
<li>
{{ member + "." + PROPERTIES_SUFFIX }}
</li>
</ul>
</details>
{% else %}
<label for="zip_member">{{ member }}</label>
<form action="/files/unzip" method="post">
<input name="zip_file" type="hidden" value="{{ file['name'] }}">
<input name="zip_member" type="hidden" value="{{ member }}">
<input type="submit" value="Unzip" onclick="processNotify('Unzipping a single file...')">
</form>
{% endif %}
</li>
{% endif %}
{% endfor %}
</ul>
</details>
</td>
{% else %}
<td>{{ file["name"] }}</td>
{% endif %}
<td style="text-align:center">
<form action="/files/download" method="post">
<input name="file" type="hidden" value="{{ base_dir }}/{{ file['name'] }}">
<input type="submit" value="{{ file['size_mb'] }} MB &#8595;">
</form>
</td>
<td>
{% if file["name"] in attached_images %}
<center>
Attached!
</center>
{% else %}
{% if file["name"].lower().endswith(ARCHIVE_FILE_SUFFIX) %}
<form action="/files/unzip" method="post">
<input name="zip_file" type="hidden" value="{{ file['name'] }}">
<input name="zip_members" type="hidden" value="{{ file['zip_members'] }}">
<input type="submit" value="Unzip All" onclick="processNotify('Unzipping all files...')">
</form>
{% else %}
<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">
{% for id in scsi_ids %}
<option name="id" value="{{id}}"{% if id == recommended_id %} selected{% endif %}>
{{ id }}
</option>
{% endfor %}
</select>
<label for="unit">LUN</label>
<input name="unit" type="number" size="2" value="0" min="0" max="31">
{% if file["detected_type"] != "UNDEFINED" %}
<input name="type" type="hidden" value="{{ file['detected_type'] }}">
{{ file["detected_type"] }}
{% else %}
<select name="type">
<option selected value="">
Type
</option>
{% for d in device_types %}
<option value="{{ d }}">
{{ d }}
</option>
{% endfor %}
{% endif %}
</select>
<input type="submit" value="Attach">
{% endif %}
</form>
<form action="/files/rename" method="post" onsubmit="var new_file_name = prompt('Enter new file name for \'{{ file["name"] }}\'', '{{ file['name'] }}'); if (new_file_name === null) event.preventDefault(); document.getElementById('new_file_name_{{ loop.index }}').value = new_file_name;">
<input name="file_name" type="hidden" value="{{ file['name'] }}">
<input name="new_file_name" id="new_file_name_{{ loop.index }}" type="hidden" value="">
<input type="submit" value="Rename">
</form>
<form action="/files/delete" method="post" onsubmit="return confirm('Delete file \'{{ file["name"] }}\'?')">
<input name="file_name" type="hidden" value="{{ file['name'] }}">
<input type="submit" value="Delete">
</form>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<p><small>Available disk space on the Pi: {{ free_disk }} MB</small></p>
<hr/>
<details>
<summary class="heading">
Attach Ethernet Adapter
</summary>
<ul>
<li>Emulates a SCSI DaynaPORT Ethernet Adapter. <a href="https://github.com/akuker/RASCSI/wiki/Dayna-Port-SCSI-Link#-macintosh-setup-instructions">Host drivers and configuration required</a>.
</li>
<li>If you have a DHCP setup, choose only the interface, and ignore the Static IP fields when attaching.</li>
<li>Configure network forwarding by running easyinstall.sh, or follow the <a href="https://github.com/akuker/RASCSI/wiki/Dayna-Port-SCSI-Link#manual-setup">manual steps in the wiki</a>.
</li>
<li style="list-style: none">{% if bridge_configured %}</li>
<li>The <tt>rascsi_bridge</tt> interface is active and ready to be used by DaynaPORT!</li>
<li style="list-style: none">{% endif %}</li>
</ul>
</details>
<table style="border: none">
<tr style="border: none">
<td style="border: none; vertical-align:top;">
<form action="/daynaport/attach" method="post">
<label for="if">Interface:</label>
<select name="if">
{% for if in netinfo["ifs"] %}
<option value="{{ if }}">
{{ if }}
</option>
{% endfor %}
</select>
<label for="ip">Static IP (optional):</label>
<input name="ip" type="text" size="15" placeholder="10.10.20.1" minlength="7" maxlength="15" pattern="^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$">
<input name="mask" type="number" size="2" placeholder="24" min="16" max="30">
<label for="scsi_id">SCSI ID:</label>
<select name="scsi_id">
{% for id in scsi_ids %}
<option value="{{ id }}"{% if id == recommended_id %} selected{% endif %}>
{{ id }}
</option>
{% endfor %}
</select>
<input type="submit" value="Attach">
</form>
</td>
</tr>
</table>
{% if macproxy_configured %}
<p><small>Macproxy is running at {{ ip_addr }} port 5000</small></p>
{% else %}
<p><small>Install <a href="https://github.com/akuker/RASCSI/wiki/Vintage-Web-Proxy#macproxy">Macproxy</a> to browse the Web with any vintage browser. It's not just for Macs!</small></p>
{% endif %}
<hr/>
<details>
<summary class="heading">
Upload File
</summary>
<ul>
<li>Uploads file to <tt>{{ base_dir }}</tt>. The largest file size accepted is {{ max_file_size }} MB.</li>
<li>For unrecognized file types, try renaming hard drive images to '.hds' and CD-ROM images to '.iso' before uploading.</li>
<li>Recognized file types: {{ valid_file_suffix }}</li>
</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"></form>
</td>
</tr>
</table>
<script type="application/javascript">
Dropzone.options.dropper = {
paramName: 'file',
acceptedFiles: '{{ valid_file_suffix }}',
chunking: true,
forceChunking: true,
url: '/files/upload',
maxFilesize: {{ max_file_size }}, // MB
chunkSize: 1000000 // bytes
}
</script>
<hr/>
<details>
<summary class="heading">
Download File to Images
</summary>
<ul>
<li>Given a URL, download that file to the <tt>{{ base_dir }}</tt> directory.</li>
</ul>
</details>
<table style="border: none">
<tr style="border: none">
<td style="border: none; vertical-align:top;">
<form action="/files/download_to_images" method="post">
<label for="url">URL:</label>
<input name="url" placeholder="URL" required="" type="url">
<input type="submit" value="Download" onclick="processNotify('Downloading File to Images...')">
</form>
</td>
</tr>
</table>
<hr/>
<details>
<summary class="heading">
Download File to AppleShare
</summary>
<ul>
<li>Given a URL, download that file to the <tt>{{ AFP_DIR }}</tt> directory and share it over AFP.</li>
<li>Manage the files you download here through AppleShare on your vintage Mac.</li>
<li>Requires <a href="https://github.com/akuker/RASCSI/wiki/AFP-File-Sharing">Netatalk</a> to be installed and configured correctly for your network.
</li>
</ul>
</details>
{% if netatalk_configured %}
<table style="border: none">
<tr style="border: none">
<td style="border: none; vertical-align:top;">
<form action="/files/download_to_afp" method="post">
<label for="url">URL:</label>
<input name="url" placeholder="URL" required="" type="url">
<input type="submit" value="Download" onclick="processNotify('Downloading File to AppleShare...')">
</form>
</td>
</tr>
</table>
{% if netatalk_configured == 1 %}
<p><small>The AppleShare server is running. No active connections</small></p>
{% elif netatalk_configured == 2 %}
<p><small>{{ netatalk_configured - 1 }} active AFP connection</small></p>
{% elif netatalk_configured > 2 %}
<p><small>{{ netatalk_configured - 1 }} active AFP connections</small></p>
{% endif %}
{% else %}
<p>Install <a href="https://github.com/akuker/RASCSI/wiki/AFP-File-Sharing">Netatalk</a> to use the AppleShare File Server.</p>
{% endif %}
<hr/>
<details>
<summary class="heading">
Download File and Create CD-ROM ISO image
</summary>
<ul>
<li>Given a URL this will download a file, create a CD-ROM image with the selected file system, and mount it on the SCSI ID given.</li>
<li>HFS is for Mac OS, Joliet for Windows, and Rock Ridge for POSIX.</li>
<li>On Mac OS, requires a <a href="https://github.com/akuker/RASCSI/wiki/Drive-Setup#Mounting_CD_ISO_or_MO_images">compatible CD-ROM driver</a> installed on the target system.
</li>
<li>If the target file is a zip archive, we will attempt to unzip it and store the resulting files only.</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 %}
<option value="{{ id }}"{% if id == 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 ISO" onclick="processNotify('Downloading File as ISO...')">
</form>
</td>
</tr>
</table>
<hr/>
<details>
<summary class="heading">
Create Empty Disk Image File
</summary>
<ul>
<li>The Generic image type is recommended for most systems</li>
<li>APPLE GENUINE and NEC GENUINE image types will make RaSCSI masquerade as a particular drive type that are recognized by Mac and PC98 systems, respectively.</li>
<li>SASI images should only be used on early X68000 or UNIX workstation systems that use this pre-SCSI standard.</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">
<option value="hds">
SCSI Hard Disk image (Generic) [.hds]
</option>
<option value="hda">
SCSI Hard Disk image (APPLE GENUINE - use with Mac) [.hda]
</option>
<option value="hdn">
SCSI Hard Disk image (NEC GENUINE - use with PC98) [.hdn]
</option>
<option value="hdr">
SCSI Removable Media Disk image (Generic) [.hdr]
</option>
<option value="hdf">
SASI Hard Disk image (use with X68000) [.hdf]
</option>
</select>
<label for="size">Size:</label>
<input name="size" type="number" placeholder="MB" min="1" size="6" required>
<input type="submit" value="Create">
</form>
</td>
</tr>
</table>
<hr/>
<details>
<summary class="heading">
Create Named Drive
</summary>
<ul>
<li>Here you can create pairs of images and properties files from a list of real-life drives.</li>
<li>This will make RaSCSI use certain vendor strings and block sizes that may improve compatibility with certain systems</li>
</ul>
</details>
<p><a href="/drive/list">Create a named disk image that mimics real-life drives</a></p>
<hr/>
<details>
<summary class="heading">
Logging
</summary>
<ul>
<li>Get a certain number of lines of service 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" placeholder="200" min="1" size="4">
<label for="scope">Scope:</label>
<select name="scope">
<option value="default">
default
</option>
<option value="rascsi">
rascsi.service
</option>
<option value="rascsi-web">
rascsi-web.service
</option>
</select>
<input type="submit" value="Show Logs">
</form>
</td>
</tr>
</table>
<hr/>
<details>
<summary class="heading">
Server Log Level
</summary>
<ul>
<li>Change the log level of the RaSCSI backend service.</li>
<li>The dropdown will indicate the current 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>
<hr/>
<details>
<summary class="heading">
Raspberry Pi Operations
</summary>
<ul>
<li>Issue reboot or shutdown commands to the Raspberry Pi.</li>
<li>You can also restart the RaSCSI backend service here.</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>
<td style="border: none; vertical-align:top;">
<form action="/rascsi/restart" method="post" onsubmit="return confirm('Restart RaSCSI?')">
<input type="submit" value="Restart RaSCSI Service">
</form>
</td>
</tr>
</table>
{% endblock content %}