refactoring

This commit is contained in:
Maxim Devaev 2025-01-30 10:34:36 +02:00
parent 4039ae0483
commit 697ef549b9
23 changed files with 1150 additions and 1065 deletions

View File

@ -22,18 +22,21 @@ doctype html
# #
==============================================================================
- var css_dir = "/share/css"
- var js_dir = "/share/js"
- var svg_dir = "/share/svg"
- var png_dir = "/share/png"
-
var css_dir = "/share/css"
var js_dir = "/share/js"
var svg_dir = "/share/svg"
var png_dir = "/share/png"
title = ""
main_js = ""
body_class = ""
css_list = ["vars", "main"]
- var title = ""
- var main_js = ""
- var body_class = ""
- var css_list = ["vars", "main"]
block vars
html(lang="en")
head
meta(charset="utf-8")

View File

@ -1,45 +1,48 @@
extends start.pug
append vars
- title = "PiKVM Index"
- main_js = "index/main"
- css_list = css_list.concat(["window", "modal", "index/index"])
-
title = "PiKVM Index"
main_js = "index/main"
css_list = css_list.concat(["window", "modal", "index/index"])
block start
table
tr
td(class="logo")
td.logo
a(href="https://pikvm.org" target="_blank")
img(class="svg-gray" src=`${svg_dir}/logo.svg` alt="PiKVM" height="40")
img.svg-gray(src=`${svg_dir}/logo.svg` alt="PiKVM" height="40")
td
table
tr #[td(colspan="2" class="title") The Open Source KVM over IP]
tr #[td.title(colspan="2") The Open Source KVM over IP]
tr
td(colspan="2" class="copyright")
td.copyright(colspan="2")
| Copyright © 2018-2024 #[a(target="_blank" href="mailto:mdevaev@gmail.com") Maxim Devaev]
hr
table
td(class="server")
td Server:
td #[a(id="kvmd-meta-server-host" target="_blank" href="/api/info")]
td #[a#kvmd-meta-server-host(target="_blank" href="/api/info")]
hr
div(id="apps-box")
#apps-box
h4 Loading ...
div(id="app-keyboard-warning")
#app-keyboard-warning
hr
p(class="text")
p.text
| Please note that when you are working with a KVM session or another application that captures the keyboard,
| you can't use some keyboard shortcuts such as Ctrl+Alt+Del (which will be caught by your OS) or Ctrl+W (caught by your browser).
p(class="text")
p.text
| To override this limitation you can use #[a(target="_blank" href="https://google.com/chrome") Google Chrome]
| or #[a(target="_blank" href="https://chromium.org/Home") Chromium] in application mode.
div(id="app-text" class="code")
.code#app-text
hr
p(class="text credits")
p.text.credits
a(target="_blank" href="https://pikvm.org") PiKVM Project
|   |  
a(target="_blank" href="https://docs.pikvm.org") Documentation

View File

@ -1,20 +1,23 @@
extends ../start.pug
append vars
- title = "PiKVM IPMI Info"
- main_js = "ipmi/main"
- index_link = true
-
title = "PiKVM IPMI Info"
main_js = "ipmi/main"
index_link = true
block start
p(class="text")
p.text
| This PiKVM device has running #[b kvmd-ipmi] daemon and provides IPMI 2.0 interface for some basic
| BMC operations like on/off/reset the server.
p(class="text")
p.text
| #[b WARNING!] We strongly don't recommend you to use IPMI in untrusted networks because
| this protocol is completely unsafe by design. In short, the authentication process for IPMI mandates
| that the server send a salted SHA1 or MD5 hash of the requested user's password to the client,
| prior to the client authenticating.
p(class="text")
p.text
| #[b NEVER] use the same passwords for KVMD and IPMI users. And even better not to use IPMI.
| Instead, you can directly use KVMD API via curl. Here some examples:
div(id="ipmi-text" class="code" style="max-height:200px")
.code#ipmi-text(style="max-height:200px")

View File

@ -151,7 +151,7 @@
<button class="small" data-force-hide-menu data-show-window="about-window">&bull; About</button>
</td>
<td id="system-tool-log">
<button class="small" data-force-hide-menu id="open-log-button">&bull; Log</button>
<button class="small" id="open-log-button" data-force-hide-menu>&bull; Log</button>
</td>
<td class="feature-disabled" id="system-tool-wol">
<button class="__gpio-button-__wol__ __gpio-button small" data-force-hide-menu data-channel="__wol__" data-confirm="Are you sure to send Wake-on-LAN packet to the server?">&bull; WoL</button>
@ -196,55 +196,61 @@
<tr class="feature-disabled" id="stream-resolution">
<td>Resolution:</td>
<td>
<select disabled id="stream-resolution-selector"></select>
<select id="stream-resolution-selector" disabled></select>
</td>
</tr>
<tr class="feature-disabled" id="stream-quality">
<td>JPEG quality:</td>
<td>JPEG quality:
</td>
<td class="value-slider">
<input class="slider" disabled type="range" id="stream-quality-slider">
<input class="slider" type="range" id="stream-quality-slider">
</td>
<td class="value-number" id="stream-quality-value"></td>
</tr>
<tr>
<td>JPEG max fps:</td>
<td>JPEG max fps:
</td>
<td class="value-slider">
<input class="slider" disabled type="range" id="stream-desired-fps-slider">
<input class="slider" type="range" id="stream-desired-fps-slider">
</td>
<td class="value-number" id="stream-desired-fps-value"></td>
</tr>
<tr class="feature-disabled" id="stream-h264-bitrate">
<td>H.264 kbps:</td>
<td>H.264 kbps:
</td>
<td class="value-slider">
<input class="slider" disabled type="range" id="stream-h264-bitrate-slider">
<input class="slider" type="range" id="stream-h264-bitrate-slider">
</td>
<td class="value-number" id="stream-h264-bitrate-value"></td>
</tr>
<tr class="feature-disabled" id="stream-h264-gop">
<td>H.264 <a target="_blank" href="https://docs.pikvm.org/webrtc">gop</a>:</td>
<td>H.264 <a target="_blank" href="https://docs.pikvm.org/webrtc">gop</a>:
</td>
<td class="value-slider">
<input class="slider" disabled type="range" id="stream-h264-gop-slider">
<input class="slider" type="range" id="stream-h264-gop-slider">
</td>
<td class="value-number" id="stream-h264-gop-value"></td>
</tr>
<tr class="feature-disabled" id="stream-mode">
<td>Video <a target="_blank" href="https://docs.pikvm.org/webrtc">mode</a>:</td>
<td><a target="_blank" href="https://docs.pikvm.org/webrtc">Video mode</a>:
</td>
<td>
<div class="radio-box">
<input type="radio" id="stream-mode-radio-janus" name="stream-mode-radio" value="janus">
<label for="stream-mode-radio-janus">WebRTC</label>
<input type="radio" id="stream-mode-radio-media" name="stream-mode-radio" value="media">
<label for="stream-mode-radio-media">H.264</label>
<input checked type="radio" id="stream-mode-radio-mjpeg" name="stream-mode-radio" value="mjpeg">
<input type="radio" id="stream-mode-radio-mjpeg" name="stream-mode-radio" value="mjpeg" checked>
<label for="stream-mode-radio-mjpeg">MJPEG</label>
</div>
</td>
</tr>
<tr class="feature-disabled" id="stream-orient">
<td>Orientation:</td>
<td>Orientation:
</td>
<td>
<div class="radio-box">
<input checked type="radio" id="stream-orient-radio-0" name="stream-orient-radio" value="0">
<input type="radio" id="stream-orient-radio-0" name="stream-orient-radio" value="0" checked>
<label for="stream-orient-radio-0">Default</label>
<input type="radio" id="stream-orient-radio-90" name="stream-orient-radio" value="90">
<label for="stream-orient-radio-90">90&deg;</label>
@ -256,14 +262,16 @@
</td>
</tr>
<tr class="feature-disabled" id="stream-audio">
<td>Audio volume:</td>
<td>Audio volume:
</td>
<td class="value-slider">
<input class="slider" type="range" id="stream-audio-volume-slider">
</td>
<td class="value-number" id="stream-audio-volume-value"></td>
</tr>
<tr class="feature-disabled" id="stream-mic">
<td>Microphone:</td>
<td>Microphone:
</td>
<td align="right">
<div class="switch-box">
<input disabled type="checkbox" id="stream-mic-switch">
@ -275,7 +283,7 @@
<hr>
<div class="buttons buttons-row">
<button class="row33" data-force-hide-menu data-show-window="stream-window">&bull; Show stream</button>
<button class="row33" data-force-hide-menu id="stream-screenshot-button">&bull; Screenshot</button>
<button class="row33" id="stream-screenshot-button" data-force-hide-menu>&bull; Screenshot</button>
<button class="row33" id="stream-reset-button">Reset stream</button>
</div>
<hr>
@ -287,7 +295,7 @@
</td>
</tr>
<tr class="feature-disabled" id="hid-outputs-mouse">
<td>Mouse <a target="_blank" href="https://docs.pikvm.org/mouse">mode</a>:</td>
<td><a target="_blank" href="https://docs.pikvm.org/mouse">Mouse mode</a>:</td>
<td>
<div class="radio-box" id="hid-outputs-mouse-box"></div>
</td>
@ -298,7 +306,8 @@
<div class="spoiler">
<table class="kv">
<tr>
<td>Swap Left Ctrl and Caps keys:</td>
<td>Swap Left Ctrl and Caps keys:
</td>
<td align="right">
<div class="switch-box">
<input type="checkbox" id="hid-keyboard-swap-cc-switch">
@ -310,21 +319,24 @@
<hr>
<table class="kv">
<tr>
<td>Mouse polling:</td>
<td>Mouse polling:
</td>
<td class="value-slider">
<input class="slider" type="range" id="hid-mouse-rate-slider">
</td>
<td class="value-number" id="hid-mouse-rate-value"></td>
</tr>
<tr class="feature-disabled" id="hid-mouse-sens">
<td>Relative sensitivity:</td>
<td>Relative sensitivity:
</td>
<td class="value-slider">
<input class="slider" disabled type="range" id="hid-mouse-sens-slider">
<input class="slider" type="range" id="hid-mouse-sens-slider">
</td>
<td class="value-number" id="hid-mouse-sens-value"></td>
</tr>
<tr class="feature-disabled" id="hid-mouse-squash">
<td>Squash relative moves:</td>
<td>Squash relative moves:
</td>
<td align="right">
<div class="switch-box">
<input checked type="checkbox" id="hid-mouse-squash-switch">
@ -337,7 +349,8 @@
<td>
<table>
<tr>
<td>Y:</td>
<td>Y:
</td>
<td align="right">
<div class="switch-box">
<input type="checkbox" id="hid-mouse-reverse-scrolling-switch">
@ -345,7 +358,8 @@
</div>
</td>
<td>&nbsp;&nbsp;</td>
<td>X:</td>
<td>X:
</td>
<td align="right">
<div class="switch-box">
<input type="checkbox" id="hid-mouse-reverse-panning-switch">
@ -357,7 +371,8 @@
</td>
</tr>
<tr>
<td>Cumulative scrolling:</td>
<td>Cumulative scrolling:
</td>
<td align="right">
<div class="switch-box">
<input type="checkbox" id="hid-mouse-cumulative-scrolling-switch">
@ -366,14 +381,16 @@
</td>
</tr>
<tr>
<td>Scroll rate:</td>
<td>Scroll rate:
</td>
<td class="value-slider">
<input class="slider" type="range" id="hid-mouse-scroll-slider">
</td>
<td class="value-number" id="hid-mouse-scroll-value"></td>
</tr>
<tr>
<td>Show the blue dot:</td>
<td>Show the blue dot:
</td>
<td align="right">
<div class="switch-box">
<input checked type="checkbox" id="hid-mouse-dot-switch">
@ -389,7 +406,8 @@
<div class="spoiler">
<table class="kv">
<tr>
<td>Ask page close confirmation:</td>
<td>Ask page close confirmation:
</td>
<td align="right">
<div class="switch-box">
<input checked type="checkbox" id="page-close-ask-switch">
@ -398,7 +416,8 @@
</td>
</tr>
<tr>
<td>Expand for the entire tab by default:</td>
<td>Expand for the entire tab by default:
</td>
<td align="right">
<div class="switch-box">
<input type="checkbox" id="page-full-tab-stream-switch">
@ -411,7 +430,8 @@
</details>
<table class="kv">
<tr>
<td>Bad link mode (release keys immediately):</td>
<td>Bad link mode (release keys immediately):
</td>
<td align="right">
<div class="switch-box">
<input type="checkbox" id="hid-keyboard-bad-link-switch">
@ -420,7 +440,8 @@
</td>
</tr>
<tr class="feature-disabled" id="hid-connect">
<td>Connect HID to Server:</td>
<td>Connect HID to Server:
</td>
<td align="right">
<div class="switch-box">
<input checked type="checkbox" id="hid-connect-switch">
@ -429,7 +450,8 @@
</td>
</tr>
<tr class="feature-disabled" id="hid-jiggler">
<td><a href="https://docs.pikvm.org/mouse_jiggler" target="_blank">Mouse jiggler</a>:</td>
<td><a target="_blank" href="https://docs.pikvm.org/mouse_jiggler">Mouse jiggler:</a>
</td>
<td align="right">
<div class="switch-box">
<input disabled type="checkbox" id="hid-jiggler-switch">
@ -438,7 +460,8 @@
</td>
</tr>
<tr>
<td>Mute all input HID events:</td>
<td>Mute all input HID events:
</td>
<td align="right">
<div class="switch-box">
<input type="checkbox" id="hid-mute-switch">
@ -447,7 +470,8 @@
</td>
</tr>
<tr class="feature-disabled" id="v3-usb-breaker">
<td>Connect main USB to Server:</td>
<td>Connect main USB to Server:
</td>
<td align="right">
<div class="switch-box">
<input class="__gpio-switch-__v3_usb_breaker__ gpio-switch" disabled type="checkbox" id="__gpio-switch-__v3_usb_breaker__" data-channel="__v3_usb_breaker__" data-confirm-off="Turning off this switch will disconnect the main USB from the server. Are you sure you want to continue?">
@ -456,7 +480,8 @@
</td>
</tr>
<tr class="feature-disabled" id="v4-locator">
<td>Enable locator LED:</td>
<td>Enable locator LED:
</td>
<td align="right">
<div class="switch-box">
<input class="__gpio-switch-__v4_locator__ gpio-switch" disabled type="checkbox" id="__gpio-switch-__v4_locator__" data-channel="__v4_locator__" data-confirm-off="">
@ -468,7 +493,7 @@
<hr>
<div class="buttons buttons-row">
<button class="row50" data-force-hide-menu data-show-window="keyboard-window">&bull; Show keyboard</button>
<button class="row50" disabled id="hid-reset-button">Reset HID</button>
<button class="row50" id="hid-reset-button" disabled>Reset HID</button>
</div>
</div>
</li>
@ -478,7 +503,8 @@
<hr>
<table class="kv">
<tr>
<td>Ask click confirmation:</td>
<td>Ask click confirmation:
</td>
<td align="right">
<div class="switch-box">
<input checked type="checkbox" id="atx-ask-switch">
@ -489,10 +515,10 @@
</table>
<hr>
<div class="buttons">
<button disabled data-force-hide-menu id="atx-power-button">&bull; Click Power <sup><i>short</i></sup></button>
<button disabled data-force-hide-menu id="atx-power-button-long">&bull; Click Power <sup><i>long</i></sup></button>
<button id="atx-power-button" disabled data-force-hide-menu>&bull; Click Power <sup><i>short</i></sup></button>
<button id="atx-power-button-long" disabled data-force-hide-menu>&bull; Click Power <sup><i>long</i></sup></button>
<hr>
<button disabled data-force-hide-menu id="atx-reset-button">&bull; Click Reset</button>
<button id="atx-reset-button" disabled data-force-hide-menu>&bull; Click Reset</button>
</div>
</div>
</li>
@ -519,7 +545,7 @@
<td style="line-height:1.5"><b>Current image is broken!</b></td>
</tr>
<tr>
<td><sup style="line-height:1">Perhaps uploading was interrupted<br></sup></td>
<td><sup style="line-height:1">Perhaps uploading was interrupted</sup></td>
</tr>
</table>
</div>
@ -587,29 +613,31 @@
<tr>
<td>Image:</td>
<td width="100%">
<select disabled id="msd-image-selector"></select>
<select id="msd-image-selector" disabled></select>
</td>
<td>
<button disabled id="msd-download-button" title="Download image"><b>&nbsp;&nbsp;&#x21E9;&nbsp;&nbsp;</b></button>
<button id="msd-download-button" disabled title="Download image"><b>&nbsp;&nbsp;&#x21E9;&nbsp;&nbsp;</b></button>
</td>
<td>
<button disabled id="msd-remove-button" title="Remove image"><b>&nbsp;&nbsp;&times;&nbsp;&nbsp;</b></button>
<button id="msd-remove-button" disabled title="Remove image"><b>&nbsp;&nbsp;&times;&nbsp;&nbsp;</b></button>
</td>
</tr>
</table>
<table class="kv">
<tr>
<td>Drive <a target="_blank" href="https://docs.pikvm.org/msd">mode</a>:</td>
<td>Drive <a target="_blank" href="https://docs.pikvm.org/msd">mode</a>:
</td>
<td>
<div class="radio-box">
<input checked type="radio" id="msd-mode-radio-cdrom" name="msd-mode-radio" value="1">
<label for="msd-mode-radio-cdrom">CD/DVD</label>
<input type="radio" id="msd-mode-radio-flash" name="msd-mode-radio" value="0">
<label for="msd-mode-radio-flash">Flash</label>
<input type="radio" id="msd-mode-radio-1" name="msd-mode-radio" value="1" checked>
<label for="msd-mode-radio-1">CD/DVD</label>
<input type="radio" id="msd-mode-radio-0" name="msd-mode-radio" value="0">
<label for="msd-mode-radio-0">Flash</label>
</div>
</td>
<td>&nbsp;</td>
<td>Writable:</td>
<td>Writable:
</td>
<td align="right">
<div class="switch-box">
<input disabled type="checkbox" id="msd-rw-switch">
@ -622,12 +650,12 @@
<div id="msd-storages"></div>
<hr>
<div class="buttons buttons-row">
<button class="row50" disabled id="msd-select-new-button">Select image to upload</button>
<button class="row25" disabled id="msd-upload-new-button">Upload</button>
<button class="row25" disabled id="msd-abort-new-button">Abort</button>
<button class="row50" id="msd-select-new-button" disabled>Select image to upload</button>
<button class="row25" id="msd-upload-new-button" disabled>Upload</button>
<button class="row25" id="msd-abort-new-button" disabled>Abort</button>
</div>
<div class="hidden" id="msd-message-another-user-uploads">
<hr>
<div class="hidden" id="msd-message-another-user-uploads">
<div class="text">
<table>
<tr>
@ -636,20 +664,20 @@
</tr>
</table>
</div>
<hr>
</div>
<div class="hidden" id="msd-new-sub">
<hr>
<table class="kv">
<tr>
<td>Specify a local file:</td>
<td>
<input type="file" id="msd-new-file">
<input id="msd-new-file" type="file">
</td>
</tr>
<tr>
<td><b>Or</b> paste a URL:</td>
<td>
<input type="text" id="msd-new-url" style="width: 100%">
<input id="msd-new-url" type="text" style="width: 100%">
</td>
</tr>
<tr class="hidden" id="msd-new-part">
@ -659,9 +687,9 @@
</td>
</tr>
</table>
<hr>
</div>
<div class="hidden" id="msd-uploading-sub">
<hr>
<table class="kv">
<tr>
<td>New image:</td>
@ -675,9 +703,9 @@
<div class="text">
<div class="progress" id="msd-uploading-progress"><span class="progress-value" id="msd-uploading-progress-value"></span></div>
</div>
<hr>
</div>
<div class="hidden" id="msd-new-tips">
<hr>
<table class="kv">
<tr>
<td class="value">Note:</td>
@ -688,12 +716,12 @@
<td>&bull; To speed up the upload, close the stream window.</td>
</tr>
</table>
</div>
<hr>
</div>
<div class="buttons buttons-row">
<button class="row50" disabled id="msd-connect-button">Connect drive to Server</button>
<button class="row25" disabled id="msd-disconnect-button">Disconnect</button>
<button class="row25" disabled id="msd-reset-button">Reset</button>
<button class="row50" id="msd-connect-button">Connect drive to Server</button>
<button class="row25" id="msd-disconnect-button">Disconnect</button>
<button class="row25" id="msd-reset-button">Reset</button>
</div>
</div>
</li>
@ -702,16 +730,16 @@
<div class="text"><b>Record and play HID/ATX/GPIO actions<br></b><sub>For security reasons, the record will not be saved on the PiKVM</sub></div>
<hr>
<div class="buttons buttons-row">
<button class="row25" disabled data-force-hide-menu id="hid-recorder-record">&bull; Rec</button>
<button class="row25" disabled id="hid-recorder-stop">Stop</button>
<button class="row25" disabled id="hid-recorder-play">Play</button>
<button class="row25" disabled id="hid-recorder-clear">Clear</button>
<button class="row25" id="hid-recorder-record" disabled data-force-hide-menu>&bull; Rec</button>
<button class="row25" id="hid-recorder-stop" disabled>Stop</button>
<button class="row25" id="hid-recorder-play" disabled>Play</button>
<button class="row25" id="hid-recorder-clear" disabled>Clear</button>
</div>
<hr>
<table class="kv">
<tr>
<td>Script time:</td>
<td class="value" colspan="2" id="hid-recorder-time">00:00:00.0</td>
<td class="value" id="hid-recorder-time" colspan="2">00:00:00.0</td>
</tr>
<tr>
<td>Scripted events:</td>
@ -722,7 +750,8 @@
<hr>
<table class="kv">
<tr>
<td>Infinite loop playback:</td>
<td>Infinite loop playback:
</td>
<td align="right">
<div class="switch-box">
<input disabled type="checkbox" id="hid-recorder-loop-switch">
@ -732,10 +761,10 @@
</tr>
</table>
<hr>
<input type="file" id="hid-recorder-new-script-file">
<input id="hid-recorder-new-script-file" type="file">
<div class="buttons buttons-row">
<button class="row50" disabled id="hid-recorder-upload">Upload script</button>
<button class="row50" disabled id="hid-recorder-download">Download script</button>
<button class="row50" id="hid-recorder-upload" disabled>Upload script</button>
<button class="row50" id="hid-recorder-download" disabled>Download script</button>
</div>
</div>
</li>
@ -749,7 +778,7 @@
<table class="kv">
<tr>
<td>
<button disabled data-force-hide-menu id="hid-pak-button">&bull; Paste</button>
<button id="hid-pak-button" disabled data-force-hide-menu>&bull; Paste</button>
</td>
<td>using host keymap</td>
<td>
@ -759,7 +788,8 @@
</table>
<table class="kv">
<tr>
<td>Slow typing:</td>
<td>Slow typing:
</td>
<td align="right">
<div class="switch-box">
<input type="checkbox" id="hid-pak-slow-switch">
@ -768,7 +798,8 @@
</td>
</tr>
<tr>
<td>Hide input text:</td>
<td>Hide input text:
</td>
<td align="right">
<div class="switch-box">
<input type="checkbox" id="hid-pak-secure-switch">
@ -777,7 +808,8 @@
</td>
</tr>
<tr>
<td>Ask paste confirmation:</td>
<td>Ask paste confirmation:
</td>
<td align="right">
<div class="switch-box">
<input checked type="checkbox" id="hid-pak-ask-switch">
@ -794,7 +826,7 @@
<table class="kv">
<tr>
<td>
<button data-force-hide-menu id="stream-ocr-button">&bull; Select area</button>
<button id="stream-ocr-button" data-force-hide-menu>&bull; Select area</button>
</td>
<td>for</td>
<td>
@ -866,25 +898,26 @@
<hr>
<div class="buttons">
<div class="buttons-row">
<button class="row25" data-shortcut="AltLeft PrintScreen KeyF" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center;" title="Call the OOM killer to kill a memory hog process">F</button>
<button class="row25" data-shortcut="AltLeft PrintScreen KeyM" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center;" title="Dump current memory info to the console">M</button>
<button class="row25" data-shortcut="AltLeft PrintScreen KeyD" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center;" title="Show all locks that are held">D</button>
<button class="row25" data-shortcut="AltLeft PrintScreen KeyT" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center;" title="Dump a list of current tasks and their information to the console">T</button>
<button class="row25" data-shortcut="AltLeft PrintScreen KeyF" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center" title="Call the OOM killer to kill a memory hog process">F</button>
<button class="row25" data-shortcut="AltLeft PrintScreen KeyM" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center" title="Dump current memory info to the console">M</button>
<button class="row25" data-shortcut="AltLeft PrintScreen KeyD" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center" title="Show all locks that are held">D</button>
<button class="row25" data-shortcut="AltLeft PrintScreen KeyT" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center" title="Dump a list of current tasks and their information to the console">T</button>
</div>
<hr>
<div class="buttons-row">
<button class="row16" data-shortcut="AltLeft PrintScreen KeyR" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center;" title="Turn off keyboard raw mode, set it to XLATE">R</button>
<button class="row16" data-shortcut="AltLeft PrintScreen KeyE" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center;" title="Send a SIGTERM to all processes, except for init">E</button>
<button class="row16" data-shortcut="AltLeft PrintScreen KeyI" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center;" title="Send a SIGKILL to all processes, except for init">I</button>
<button class="row16" data-shortcut="AltLeft PrintScreen KeyS" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center;" title="Attempt to sync all mounted filesystems">S</button>
<button class="row16" data-shortcut="AltLeft PrintScreen KeyU" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center;" title="Attempt to remount all mounted filesystems read-only">U</button>
<button class="row16" data-shortcut="AltLeft PrintScreen KeyB" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center;" title="Immediately reboot the system without syncing or unmounting disks">B</button>
<button class="row16" data-shortcut="AltLeft PrintScreen KeyR" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center" title="Turn off keyboard raw mode, set it to XLATE">R</button>
<button class="row16" data-shortcut="AltLeft PrintScreen KeyE" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center" title="Send a SIGTERM to all processes, except for init">E</button>
<button class="row16" data-shortcut="AltLeft PrintScreen KeyI" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center" title="Send a SIGKILL to all processes, except for init">I</button>
<button class="row16" data-shortcut="AltLeft PrintScreen KeyS" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center" title="Attempt to sync all mounted filesystems">S</button>
<button class="row16" data-shortcut="AltLeft PrintScreen KeyU" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center" title="Attempt to remount all mounted filesystems read-only">U</button>
<button class="row16" data-shortcut="AltLeft PrintScreen KeyB" data-shortcut-confirm="hid-sysrq-ask-switch" style="text-align: center" title="Immediately reboot the system without syncing or unmounting disks">B</button>
</div>
</div>
<hr>
<table class="kv">
<tr>
<td>Ask the magic confirmation:</td>
<td>Ask the magic confirmation:
</td>
<td align="right">
<div class="switch-box">
<input checked type="checkbox" id="hid-sysrq-ask-switch">
@ -900,7 +933,7 @@
</li>
<li class="right feature-disabled" id="switch-dropdown"><a class="menu-button" id="switch-menu-button" href="#"><img class="led-gray" id="switch-atx-power-led" src="/share/svg/led-atx-power.svg"><img class="led-gray" id="switch-atx-hdd-led" src="/share/svg/led-atx-hdd.svg"><span>Switch <i><sub id="switch-active-port"></sub></i></span></a>
<div class="menu" id="switch-menu">
<table style="border-spacing: 0px;">
<table style="border-spacing: 0px">
<tr>
<td>
<div class="text"><b><a target="_blank" href="https://docs.pikvm.org/switch">PiKVM Switch</a> is attached<br></b><sub>Select a port or perform any available action like ATX click</sub></div>
@ -921,7 +954,8 @@
<td style="line-height:1.5"><b>Good news! Your switch is ready to get the firmware update</b></td>
</tr>
<tr>
<td><sup style="line-height:1">Please <a target="_blank" href="https://docs.pikvm.org/switch/#firmware-updating">follow the instructions</a> when you decide to install it.</sup></td>
<td><sup style="line-height:1">Please <a target="_blank" href="https://docs.pikvm.org/switch/#firmware-updating">follow the instructions</a>
when you decide to install it.</sup></td>
</tr>
</table>
</div>
@ -929,7 +963,8 @@
</div>
<table class="kv">
<tr>
<td>Ask ATX click confirmation:</td>
<td>Ask ATX click confirmation:
</td>
<td align="right">
<div class="switch-box">
<input checked type="checkbox" id="switch-atx-ask-switch">
@ -971,21 +1006,21 @@
<div class="modifier left small rounded-right" data-code="left">
<div class="label"><b>&bull;</b><br>Hold</div>
</div>
<div class="empty" style="width:15px"></div>
<div class="empty" style="width: 15px"></div>
<div class="key wide-1 left rounded-left" data-code="middle">
<div class="label">Mid</div>
</div>
<div class="modifier left small rounded-right" data-code="middle">
<div class="label"><b>&bull;</b><br>Hold</div>
</div>
<div class="empty" style="width:15px"></div>
<div class="empty" style="width: 15px"></div>
<div class="modifier right small rounded-left" data-code="right">
<div class="label"><b>&bull;</b><br>Hold</div>
</div>
<div class="key wide-3 right rounded-right" data-code="right">
<div class="label">Right</div>
</div>
<div class="empty" style="width:30px"></div>
<div class="empty" style="width: 30px"></div>
<div class="key small rounded-left" data-code="up">
<div class="label">Up</div>
</div>
@ -1798,7 +1833,7 @@
</div>
</div>
<div class="spacer"></div>
<div class="key wide-2 right" data-code="Backspace" style="width:101px">
<div class="key wide-2 right" data-code="Backspace" style="width: 101px">
<div class="label">&#8612;
</div>
</div>
@ -1869,7 +1904,7 @@
</div>
</div>
<div class="spacer"></div>
<div class="key wide-1 left" data-code="Backslash" style="width:78px">
<div class="key wide-1 left" data-code="Backslash" style="width: 78px">
<div class="label">|<br>&bsol;
</div>
</div>
@ -1935,7 +1970,7 @@
</div>
</div>
<div class="spacer"></div>
<div class="key wide-3 right small" data-code="Enter" style="width:116px">
<div class="key wide-3 right small" data-code="Enter" style="width: 116px">
<div class="label">Enter<br>&crarr;
</div>
</div>
@ -2027,7 +2062,7 @@
</div>
</div>
<div class="spacer"></div>
<div class="key " data-code="Space" style="width:190px">
<div class="key " data-code="Space" style="width: 190px">
<div class="label">
</div>
</div>
@ -2075,7 +2110,7 @@
</div>
</div>
</div>
<div class="window" id="switch-window" style="width:min-content">
<div class="window" id="switch-window" style="width: min-content">
<div class="window-header">
<div class="window-grab">Switch settings</div>
<button class="window-button-close"><b>&times;</b></button>
@ -2089,7 +2124,7 @@
<td colspan="2">
<select id="switch-edid-selector" size="8"></select>
</td>
<td rowspan="2" style="vertical-align:top">
<td rowspan="2" style="vertical-align: top">
<table class="kv">
<tr>
<td>Manufacturer:</td>
@ -2118,7 +2153,7 @@
<tr>
<td>Data:</td>
<td>
<button class="small" disabled id="switch-edid-copy-data-button">Copy</button>
<button class="small" id="switch-edid-copy-data-button" disabled>Copy</button>
</td>
</tr>
</table>
@ -2128,8 +2163,8 @@
<td>
<button id="switch-edid-add-button">Add new</button>
</td>
<td style="float:right">
<button disabled id="switch-edid-remove-button">Remove</button>
<td style="float: right">
<button id="switch-edid-remove-button" disabled>Remove</button>
</td>
</tr>
</table>
@ -2138,30 +2173,13 @@
<label for="switch-tab-colors-button">Color scheme</label>
<div class="tab">
<table>
<!--tr
td Role
td Color
td Brightness
td
td Reset
-->
<!--trtd
<hr>
td
<hr>
td
<hr>
td
td
<hr>
-->
<tr>
<td style="white-space: nowrap">Selected port:</td>
<td>
<input type="color" id="switch-color-active-input">
</td>
<td>
<input type="range" id="switch-color-active-brightness-slider" style="min-width:150px">
<input type="range" id="switch-color-active-brightness-slider" style="min-width: 150px">
</td>
<td>&nbsp;&nbsp;&nbsp;</td>
<td>
@ -2174,7 +2192,7 @@
<input type="color" id="switch-color-inactive-input">
</td>
<td>
<input type="range" id="switch-color-inactive-brightness-slider" style="min-width:150px">
<input type="range" id="switch-color-inactive-brightness-slider" style="min-width: 150px">
</td>
<td>&nbsp;&nbsp;&nbsp;</td>
<td>
@ -2187,7 +2205,7 @@
<input type="color" id="switch-color-beacon-input">
</td>
<td>
<input type="range" id="switch-color-beacon-brightness-slider" style="min-width:150px">
<input type="range" id="switch-color-beacon-brightness-slider" style="min-width: 150px">
</td>
<td>&nbsp;&nbsp;&nbsp;</td>
<td>
@ -2215,7 +2233,7 @@
<input type="color" id="switch-color-flashing-input">
</td>
<td>
<input type="range" id="switch-color-flashing-brightness-slider" style="min-width:150px">
<input type="range" id="switch-color-flashing-brightness-slider" style="min-width: 150px">
</td>
<td>&nbsp;&nbsp;&nbsp;</td>
<td>
@ -2228,7 +2246,7 @@
<input type="color" id="switch-color-bootloader-input">
</td>
<td>
<input type="range" id="switch-color-bootloader-brightness-slider" style="min-width:150px">
<input type="range" id="switch-color-bootloader-brightness-slider" style="min-width: 150px">
</td>
<td>&nbsp;&nbsp;&nbsp;</td>
<td>

View File

@ -1,30 +1,33 @@
extends ../base.pug
append vars
- title = "PiKVM Session"
- main_js = "kvm/main"
- body_class = "body-no-select"
- css_list = css_list.concat(["navbar", "window", "modal", "led", "slider", "switch", "radio", "progress", "keypad", "tabs"])
- css_list = css_list.concat(["kvm/stream", "kvm/hid", "kvm/msd", "kvm/system", "kvm/keyboard", "kvm/about"])
-
title = "PiKVM Session"
main_js = "kvm/main"
body_class = "body-no-select"
css_list = css_list.concat(["navbar", "window", "modal", "led", "slider", "switch", "radio", "progress", "keypad", "tabs"])
css_list = css_list.concat(["kvm/stream", "kvm/hid", "kvm/msd", "kvm/system", "kvm/keyboard", "kvm/about"])
block body
include navbar.pug
include windows.pug
ul(class="navbar-bg-tips")
li(class="left")
pre(id="kvmd-meta-tips-left")
li(class="right")
pre(id="kvmd-meta-tips-right")
ul.navbar-bg-tips
li.left
pre#kvmd-meta-tips-left
li.right
pre#kvmd-meta-tips-right
ul(class="footer")
li(class="left")
span(id="kvmd-meta-server-host" title="Server name (see System/About)")
ul.footer
li.left
span#kvmd-meta-server-host(title="Server name (see System/About)")
| &nbsp; | &nbsp;
span(id="kvmd-version-kvmd" title="KVMD version")
span#kvmd-version-kvmd(title="KVMD version")
| &nbsp; | &nbsp;
span(id="kvmd-version-streamer" title="Streamer version")
li(class="right")
span#kvmd-version-streamer(title="Streamer version")
li.right
a(target="_blank" href="https://pikvm.org") PiKVM Project
| &nbsp; | &nbsp;
a(target="_blank" href="https://docs.pikvm.org") Documentation

View File

@ -1,17 +1,18 @@
li(id="atx-dropdown" class="right feature-disabled")
a(class="menu-button" href="#")
li.right.feature-disabled#atx-dropdown
a.menu-button(href="#")
+navbar_led("atx-power-led", "led-atx-power")
+navbar_led("atx-hdd-led", "led-atx-hdd")
span ATX
div(class="menu")
div(class="text")
.menu
.text
b Control the server's power#[br]
sub Use the short click for ACPI shutdown
hr
+menu_switch("atx-ask-switch", "Ask click confirmation", true, true)
+menu_switch_table("atx-ask-switch", true, true) Ask click confirmation:
hr
div(class="buttons")
button(disabled data-force-hide-menu id="atx-power-button") &bull; Click Power #[sup #[i short]]
button(disabled data-force-hide-menu id="atx-power-button-long") &bull; Click Power #[sup #[i long]]
.buttons
button#atx-power-button(disabled data-force-hide-menu) &bull; Click Power #[sup #[i short]]
button#atx-power-button-long(disabled data-force-hide-menu) &bull; Click Power #[sup #[i long]]
hr
button(disabled data-force-hide-menu id="atx-reset-button") &bull; Click Reset
button#atx-reset-button(disabled data-force-hide-menu) &bull; Click Reset

View File

@ -1,4 +1,5 @@
li(id="gpio-dropdown" class="right feature-disabled")
a(class="menu-button" id="gpio-menu-button" href="#")
li.right.feature-disabled#gpio-dropdown
a.menu-button#gpio-menu-button(href="#")
span GPIO
div(id="gpio-menu" class="menu")
.menu#gpio-menu

View File

@ -1,32 +1,34 @@
div(id="hw-health-dropdown" class="hidden")
li(class="left")
a(class="menu-button" href="#")
.hidden#hw-health-dropdown
li.left
a.menu-button(href="#")
+navbar_led("hw-health-undervoltage-led", "led-undervoltage", "hidden")
+navbar_led("hw-health-overheating-led", "led-overheating", "hidden")
div(class="menu")
.menu
+menu_message("warning", "Raspberry Pi's health is at risk")
| This is not a drill! A red icon indicates a current issue,#[br]
| a yellow one that was observed since the device booted up
div(id="hw-health-message-undervoltage" class="hidden")
.hidden#hw-health-message-undervoltage
hr
+menu_message("led-undervoltage", "Undervoltage detected", "led-gray")
| Make sure your power supply and cabling are providing#[br]
| enough power to the Raspberry Pi (3A minimum)
div(id="hw-health-message-overheating" class="hidden")
.hidden#hw-health-message-overheating
hr
+menu_message("led-overheating", "Overheating detected", "led-gray")
| Frequency capping due to overheating,#[br]
| please improve cooling of the Raspberry Pi
div(id="fan-health-dropdown" class="hidden")
li(class="left")
a(class="menu-button" href="#")
.hidden#fan-health-dropdown
li.left
a.menu-button(href="#")
+navbar_led("fan-health-led", "led-fan", "hidden")
div(class="menu")
.menu
+menu_message("warning", "Raspberry Pi's health is at risk")
| This is not a drill! A red icon indicates a current issue,#[br]
| a yellow one that was observed in the past
div(id="fan-health-message-fail")
#fan-health-message-fail
hr
+menu_message("led-fan", "Fan failed", "led-gray")
| A fan error occured, please #[a(href="/api/log?seek=3600&follow=1" target="_blank") check the log]

View File

@ -1,30 +1,36 @@
li(id="macro-dropdown" class="right")
a(class="menu-button" href="#")
li.right#macro-dropdown
a.menu-button(href="#")
+navbar_led("hid-recorder-led", "led-gear")
span Macro
div(class="menu")
div(class="text")
.menu
.text
b Record and play HID/ATX/GPIO actions#[br]
sub For security reasons, the record will not be saved on the PiKVM
hr
div(class="buttons buttons-row")
button(disabled data-force-hide-menu id="hid-recorder-record" class="row25") &bull; Rec
button(disabled id="hid-recorder-stop" class="row25") Stop
button(disabled id="hid-recorder-play" class="row25") Play
button(disabled id="hid-recorder-clear" class="row25") Clear
.buttons.buttons-row
button.row25#hid-recorder-record(disabled data-force-hide-menu) &bull; Rec
button.row25#hid-recorder-stop(disabled) Stop
button.row25#hid-recorder-play(disabled) Play
button.row25#hid-recorder-clear(disabled) Clear
hr
table(class="kv")
table.kv
tr
td Script time:
td(colspan="2" id="hid-recorder-time" class="value") 00:00:00.0
td.value#hid-recorder-time(colspan="2") 00:00:00.0
tr
td Scripted events:
td(id="hid-recorder-events-count" class="value") 0
td.value#hid-recorder-events-count 0
td #[sup #[i include delays]]
hr
+menu_switch("hid-recorder-loop-switch", "Infinite loop playback", false, false)
+menu_switch_table("hid-recorder-loop-switch", false, false) Infinite loop playback:
hr
input(type="file" id="hid-recorder-new-script-file")
div(class="buttons buttons-row")
button(disabled id="hid-recorder-upload" class="row50") Upload script
button(disabled id="hid-recorder-download" class="row50") Download script
input#hid-recorder-new-script-file(type="file")
.buttons.buttons-row
button.row50#hid-recorder-upload(disabled) Upload script
button.row50#hid-recorder-download(disabled) Download script

View File

@ -1,100 +1,108 @@
li(id="msd-dropdown" class="right feature-disabled")
a(class="menu-button" href="#")
li.right.feature-disabled#msd-dropdown
a.menu-button(href="#")
+navbar_led("msd-led", "led-msd")
span Drive
div(id="msd-menu" class="menu")
div(class="text")
.menu#msd-menu
.text
b Mass Storage Drive:
span(id="msd-status")
span#msd-status
br
hr
div(id="msd-message-offline" class="hidden")
.hidden#msd-message-offline
+menu_message("warning", "Mass Storage Drive is offline")
hr
div(id="msd-message-image-broken" class="hidden")
.hidden#msd-message-image-broken
+menu_message("warning", "Current image is broken!")
| Perhaps uploading was interrupted#[br]
| Perhaps uploading was interrupted
hr
div(id="msd-message-too-big-for-dvd" class="hidden")
.hidden#msd-message-too-big-for-dvd
+menu_message("warning", "Current image is too big for DVD!")
| The maximum is 31.6GiB. Please switch to the Flash mode.
hr
div(id="msd-message-out-of-storage" class="hidden")
.hidden#msd-message-out-of-storage
+menu_message("warning", "Current image is out of storage")
| This image was connected manually using #[b kvmd-otgmsd]
hr
div(id="msd-message-rw-enabled" class="hidden")
.hidden#msd-message-rw-enabled
+menu_message("warning", "Read-write mode is enabled")
| Do not turn off PiKVM while this is active to prevent#[br]
| filesystem corruption. Use read-only mode where possible,#[br]
| as writing to SD card often can reduce its lifespan.
hr
div(id="msd-message-downloads" class="hidden")
.hidden#msd-message-downloads
+menu_message("info", "The image is being downloaded from PiKVM")
| Please wait
hr
table(class="kv")
table.kv
tr
td Image:
td(width="100%") #[select(disabled id="msd-image-selector")]
td #[button(disabled id="msd-download-button" title="Download image") #[b &nbsp;&nbsp;&#x21E9;&nbsp;&nbsp;]]
td #[button(disabled id="msd-remove-button" title="Remove image") #[b &nbsp;&nbsp;&times;&nbsp;&nbsp;]]
table(class="kv")
td(width="100%") #[select#msd-image-selector(disabled)]
td #[button#msd-download-button(disabled title="Download image") #[b &nbsp;&nbsp;&#x21E9;&nbsp;&nbsp;]]
td #[button#msd-remove-button(disabled title="Remove image") #[b &nbsp;&nbsp;&times;&nbsp;&nbsp;]]
table.kv
tr
td Drive #[a(target="_blank" href="https://docs.pikvm.org/msd") mode]:
td
div(class="radio-box")
input(checked type="radio" id="msd-mode-radio-cdrom" name="msd-mode-radio" value="1")
label(for="msd-mode-radio-cdrom") CD/DVD
input(type="radio" id="msd-mode-radio-flash" name="msd-mode-radio" value="0")
label(for="msd-mode-radio-flash") Flash
+menu_radio_td2("msd-mode-radio", [
{title: "CD/DVD", value: "1", checked: true},
{title: "Flash", value: "0"},
]) Drive #[a(target="_blank" href="https://docs.pikvm.org/msd") mode]:
td &nbsp;
+menu_switch_notable("msd-rw-switch", "Writable", false, false)
+menu_switch_td2("msd-rw-switch", false, false) Writable:
hr
div(id="msd-storages")
#msd-storages
hr
div(class="buttons buttons-row")
button(disabled id="msd-select-new-button" class="row50") Select image to upload
button(disabled id="msd-upload-new-button" class="row25") Upload
button(disabled id="msd-abort-new-button" class="row25") Abort
div(id="msd-message-another-user-uploads" class="hidden")
.buttons.buttons-row
button.row50#msd-select-new-button(disabled) Select image to upload
button.row25#msd-upload-new-button(disabled) Upload
button.row25#msd-abort-new-button(disabled) Abort
hr
.hidden#msd-message-another-user-uploads
+menu_message("info", "Another user uploads an image")
div(id="msd-new-sub" class="hidden")
hr
table(class="kv")
.hidden#msd-new-sub
table.kv
tr
td Specify a local file:
td #[input(type="file" id="msd-new-file")]
td #[input#msd-new-file(type="file")]
tr
td #[b Or] paste a URL:
td #[input(type="text" id="msd-new-url" style="width: 100%")]
tr(id="msd-new-part" class="hidden")
td #[input#msd-new-url(type="text" style="width: 100%")]
tr.hidden#msd-new-part
td Upload partition:
td(width="100%") #[select(id="msd-new-part-selector")]
div(id="msd-uploading-sub" class="hidden")
td(width="100%") #[select#msd-new-part-selector]
hr
table(class="kv")
.hidden#msd-uploading-sub
table.kv
tr
td New image:
td(id="msd-uploading-name" class="value")
td.value#msd-uploading-name
tr
td Upload size:
td(id="msd-uploading-size" class="value")
div(class="text")
div(id="msd-uploading-progress" class="progress")
span(id="msd-uploading-progress-value" class="progress-value")
div(id="msd-new-tips" class="hidden")
td.value#msd-uploading-size
.text
.progress#msd-uploading-progress
span.progress-value#msd-uploading-progress-value
hr
table(class="kv")
.hidden#msd-new-tips
table.kv
tr
td(class="value") Note:
td.value Note:
td &bull; Don't close the browser page until the upload is complete.
tr
td
td &bull; To speed up the upload, close the stream window.
hr
div(class="buttons buttons-row")
button(disabled id="msd-connect-button" class="row50") Connect drive to Server
button(disabled id="msd-disconnect-button" class="row25") Disconnect
button(disabled id="msd-reset-button" class="row25") Reset
.buttons.buttons-row
button.row50#msd-connect-button Connect drive to Server
button.row25#msd-disconnect-button Disconnect
button.row25#msd-reset-button Reset

View File

@ -1,47 +1,51 @@
li(id="shortcuts-dropdown" class="right")
a(class="menu-button" href="#") Shortcuts
div(id="shortcuts-menu" class="menu")
div(class="text")
li.right#shortcuts-dropdown
a.menu-button(href="#") Shortcuts
.menu#shortcuts-menu
.text
b Quick keyboard shortcuts#[br]
sub Also see #[i System &rarr; Show keyboard]
hr
div(class="buttons")
div(class="buttons-row")
button(data-force-hide-menu data-shortcut="CapsLock" class="row50")
.buttons
.buttons-row
button.row50(data-force-hide-menu data-shortcut="CapsLock")
| &bull; Caps Lock &nbsp;
img(class="inline-lamp-small hid-keyboard-caps-led led-gray" src=`${svg_dir}/led-square.svg`)
button(data-force-hide-menu data-shortcut="MetaLeft" class="row50") &bull; Left Win
img.inline-lamp-small.hid-keyboard-caps-led.led-gray(src=`${svg_dir}/led-square.svg`)
button.row50(data-force-hide-menu data-shortcut="MetaLeft") &bull; Left Win
hr
div(class="buttons-row")
button(data-force-hide-menu data-shortcut="AltLeft ShiftLeft" class="row50") &bull; Alt+Shift
button(data-force-hide-menu data-shortcut="ControlLeft KeyW" class="row50") &bull; Ctrl+W
div(class="buttons-row")
button(data-force-hide-menu data-shortcut="ControlLeft ShiftLeft" class="row50") &bull; Ctrl+Shift
button(data-force-hide-menu data-shortcut="AltLeft Tab" class="row50") &bull; Alt+Tab
div(class="buttons-row")
button(data-force-hide-menu data-shortcut="ShiftLeft ShiftRight" class="row50") &bull; Shift+Shift
button(data-force-hide-menu data-shortcut="AltLeft Enter" class="row50") &bull; Alt+Enter
div(class="buttons-row")
button(data-force-hide-menu data-shortcut="MetaLeft Space" class="row50") &bull; Win+Space
button(data-force-hide-menu data-shortcut="AltLeft F4" class="row50") &bull; Alt+F4
.buttons-row
button.row50(data-force-hide-menu data-shortcut="AltLeft ShiftLeft") &bull; Alt+Shift
button.row50(data-force-hide-menu data-shortcut="ControlLeft KeyW") &bull; Ctrl+W
.buttons-row
button.row50(data-force-hide-menu data-shortcut="ControlLeft ShiftLeft") &bull; Ctrl+Shift
button.row50(data-force-hide-menu data-shortcut="AltLeft Tab") &bull; Alt+Tab
.buttons-row
button.row50(data-force-hide-menu data-shortcut="ShiftLeft ShiftRight") &bull; Shift+Shift
button.row50(data-force-hide-menu data-shortcut="AltLeft Enter") &bull; Alt+Enter
.buttons-row
button.row50(data-force-hide-menu data-shortcut="MetaLeft Space") &bull; Win+Space
button.row50(data-force-hide-menu data-shortcut="AltLeft F4") &bull; Alt+F4
hr
div(class="buttons-row")
button(data-force-hide-menu data-shortcut="ControlLeft AltLeft F1" class="row50") &bull; Ctrl+Alt+F1
button(data-force-hide-menu data-shortcut="MetaLeft KeyL" class="row50") &bull; Win+L
div(class="buttons-row")
button(data-force-hide-menu data-shortcut="ControlLeft AltLeft F2" class="row50") &bull; Ctrl+Alt+F2
button(data-force-hide-menu data-shortcut="PrintScreen" class="row50") &bull; Print Screen
.buttons-row
button.row50(data-force-hide-menu data-shortcut="ControlLeft AltLeft F1") &bull; Ctrl+Alt+F1
button.row50(data-force-hide-menu data-shortcut="MetaLeft KeyL") &bull; Win+L
.buttons-row
button.row50(data-force-hide-menu data-shortcut="ControlLeft AltLeft F2") &bull; Ctrl+Alt+F2
button.row50(data-force-hide-menu data-shortcut="PrintScreen") &bull; Print Screen
hr
div(class="buttons-row")
button(data-force-hide-menu data-shortcut="ControlLeft AltLeft Delete" class="row50") &bull; Ctrl+Alt+Del
button(data-force-hide-menu data-shortcut="Power" class="row50") &bull; Power
.buttons-row
button.row50(data-force-hide-menu data-shortcut="ControlLeft AltLeft Delete") &bull; Ctrl+Alt+Del
button.row50(data-force-hide-menu data-shortcut="Power") &bull; Power
hr
div(class="text")
.text
| &darr; &bull; Alt+SysRq+... <sup><i>linux magic
| #[a(target="_blank" href="https://www.kernel.org/doc/html/latest/admin-guide/sysrq.html") help]</i></sup>
hr
div(class="buttons")
div(class="buttons-row")
.buttons
.buttons-row
-
let sysrq = {
"F": "Call the OOM killer to kill a memory hog process",
@ -50,9 +54,14 @@ li(id="shortcuts-dropdown" class="right")
"T": "Dump a list of current tasks and their information to the console",
}
each title, key in sysrq
button(data-shortcut=`AltLeft PrintScreen Key${key}` data-shortcut-confirm="hid-sysrq-ask-switch" class="row25" style="text-align: center;" title=`${title}`) #{key}
button.row25(
data-shortcut=`AltLeft PrintScreen Key${key}`
data-shortcut-confirm="hid-sysrq-ask-switch"
style="text-align: center"
title=`${title}`
) #{key}
hr
div(class="buttons-row")
.buttons-row
-
sysrq = {
"R": "Turn off keyboard raw mode, set it to XLATE",
@ -63,6 +72,12 @@ li(id="shortcuts-dropdown" class="right")
"B": "Immediately reboot the system without syncing or unmounting disks",
}
each title, key in sysrq
button(data-shortcut=`AltLeft PrintScreen Key${key}` data-shortcut-confirm="hid-sysrq-ask-switch" class="row16" style="text-align: center;" title=`${title}`) #{key}
button.row16(
data-shortcut=`AltLeft PrintScreen Key${key}`
data-shortcut-confirm="hid-sysrq-ask-switch"
style="text-align: center"
title=`${title}`
) #{key}
hr
+menu_switch("hid-sysrq-ask-switch", "Ask the magic confirmation", true, true)
+menu_switch_table("hid-sysrq-ask-switch", true, true) Ask the magic confirmation:

View File

@ -1,23 +1,28 @@
li(id="switch-dropdown" class="right feature-disabled")
a(class="menu-button" id="switch-menu-button" href="#")
li.right.feature-disabled#switch-dropdown
a.menu-button#switch-menu-button(href="#")
+navbar_led("switch-atx-power-led", "led-atx-power")
+navbar_led("switch-atx-hdd-led", "led-atx-hdd")
span Switch #[i #[sub(id="switch-active-port") ]]
div(id="switch-menu" class="menu")
table(style="border-spacing: 0px;")
span Switch #[i #[sub#switch-active-port]]
.menu#switch-menu
table(style="border-spacing: 0px")
tr
td
div(class="text")
.text
b #[a(target="_blank" href="https://docs.pikvm.org/switch") PiKVM Switch] is attached#[br]
sub Select a port or perform any available action like ATX click
td
div(class="text")
button(data-force-hide-menu data-show-window="switch-window" class="small") &bull; Settings
.text
button.small(data-force-hide-menu data-show-window="switch-window") &bull; Settings
hr
div(id="switch-message-update" class="hidden")
.hidden#switch-message-update
+menu_message("info", "Good news! Your switch is ready to get the firmware update")
| Please #[a(target="_blank" href="https://docs.pikvm.org/switch/#firmware-updating") follow the instructions] when you decide to install it.
| Please #[a(target="_blank" href="https://docs.pikvm.org/switch/#firmware-updating") follow the instructions]
| when you decide to install it.
hr
+menu_switch("switch-atx-ask-switch", "Ask ATX click confirmation", true, true)
+menu_switch_table("switch-atx-ask-switch", true, true) Ask ATX click confirmation:
hr
table(id="switch-chain" class="kv")
table.kv#switch-chain

View File

@ -1,148 +1,138 @@
li(id="system-dropdown" class="right")
a(class="menu-button" href="#")
li.right#system-dropdown
a.menu-button(href="#")
+navbar_led("link-led", "led-link")
+navbar_led("stream-led", "led-video")
+navbar_led("hid-keyboard-led", "led-hid-keyboard")
+navbar_led("hid-mouse-led", "led-hid-mouse")
span System
div(id="system-menu" class="menu")
table(class="kv")
.menu#system-menu
table.kv
tr
td(class="value") Runtime settings &amp; tools
td(id="system-tool-webterm" class="feature-disabled") #[button(data-force-hide-menu data-show-window="webterm-window" class="small") &bull; Term]
td(id="system-tool-about") #[button(data-force-hide-menu data-show-window="about-window" class="small") &bull; About]
td(id="system-tool-log") #[button(data-force-hide-menu id="open-log-button" class="small") &bull; Log]
td(id="system-tool-wol" class="feature-disabled")
button(data-force-hide-menu class="__gpio-button-__wol__ __gpio-button small" data-channel="__wol__"
data-confirm="Are you sure to send Wake-on-LAN packet to the server?") &bull; WoL
td.value
| Runtime settings &amp; tools
td.feature-disabled#system-tool-webterm
button.small(data-force-hide-menu data-show-window="webterm-window") &bull; Term
td#system-tool-about
button.small(data-force-hide-menu data-show-window="about-window") &bull; About
td#system-tool-log
button.small#open-log-button(data-force-hide-menu) &bull; Log
td.feature-disabled#system-tool-wol
button(
data-force-hide-menu
class="__gpio-button-__wol__ __gpio-button small"
data-channel="__wol__"
data-confirm="Are you sure to send Wake-on-LAN packet to the server?"
) &bull; WoL
hr
div(id="stream-message-no-webrtc" class="hidden")
.hidden#stream-message-no-webrtc
+menu_message("warning", "WebRTC is not supported by this browser")
hr
div(id="stream-message-no-vd" class="hidden")
.hidden#stream-message-no-vd
+menu_message("warning", "Direct HTTP H.264 streaming is not supported")
hr
div(id="stream-message-no-h264" class="hidden")
.hidden#stream-message-no-h264
+menu_message("warning", "H.264 is not supported by this browser")
hr
table(class="kv")
tr(id="stream-resolution" class="feature-disabled")
table.kv
tr.feature-disabled#stream-resolution
td Resolution:
td #[select(disabled id="stream-resolution-selector")]
tr(id="stream-quality" class="feature-disabled")
td JPEG quality:
td(class="value-slider") #[input(disabled type="range" id="stream-quality-slider" class="slider")]
td(id="stream-quality-value" class="value-number")
td #[select#stream-resolution-selector(disabled)]
tr.feature-disabled#stream-quality
+menu_slider_td3("stream-quality-slider", "stream-quality-value", false) JPEG quality:
tr
td JPEG max fps:
td(class="value-slider") #[input(disabled type="range" id="stream-desired-fps-slider" class="slider")]
td(id="stream-desired-fps-value" class="value-number")
tr(id="stream-h264-bitrate" class="feature-disabled")
td H.264 kbps:
td(class="value-slider") #[input(disabled type="range" id="stream-h264-bitrate-slider" class="slider")]
td(id="stream-h264-bitrate-value" class="value-number")
tr(id="stream-h264-gop" class="feature-disabled")
td H.264 #[a(target="_blank" href="https://docs.pikvm.org/webrtc") gop]:
td(class="value-slider") #[input(disabled type="range" id="stream-h264-gop-slider" class="slider")]
td(id="stream-h264-gop-value" class="value-number")
tr(id="stream-mode" class="feature-disabled")
td Video #[a(target="_blank" href="https://docs.pikvm.org/webrtc") mode]:
td
div(class="radio-box")
input(type="radio" id="stream-mode-radio-janus" name="stream-mode-radio" value="janus")
label(for="stream-mode-radio-janus") WebRTC
input(type="radio" id="stream-mode-radio-media" name="stream-mode-radio" value="media")
label(for="stream-mode-radio-media") H.264
input(checked type="radio" id="stream-mode-radio-mjpeg" name="stream-mode-radio" value="mjpeg")
label(for="stream-mode-radio-mjpeg") MJPEG
tr(id="stream-orient" class="feature-disabled")
td Orientation:
td
div(class="radio-box")
input(checked type="radio" id="stream-orient-radio-0" name="stream-orient-radio" value="0")
label(for="stream-orient-radio-0") Default
input(type="radio" id="stream-orient-radio-90" name="stream-orient-radio" value="90")
label(for="stream-orient-radio-90") 90&deg;
input(type="radio" id="stream-orient-radio-180" name="stream-orient-radio" value="180")
label(for="stream-orient-radio-180") 180&deg;
input(type="radio" id="stream-orient-radio-270" name="stream-orient-radio" value="270")
label(for="stream-orient-radio-270") 270&deg;
tr(id="stream-audio" class="feature-disabled")
td Audio volume:
td(class="value-slider") #[input(type="range" id="stream-audio-volume-slider" class="slider")]
td(id="stream-audio-volume-value" class="value-number")
tr(id="stream-mic" class="feature-disabled")
+menu_switch_notable("stream-mic-switch", "Microphone", false, false)
+menu_slider_td3("stream-desired-fps-slider", "stream-desired-fps-value", false) JPEG max fps:
tr.feature-disabled#stream-h264-bitrate
+menu_slider_td3("stream-h264-bitrate-slider", "stream-h264-bitrate-value", false) H.264 kbps:
tr.feature-disabled#stream-h264-gop
+menu_slider_td3("stream-h264-gop-slider", "stream-h264-gop-value", false)
|H.264 #[a(target="_blank" href="https://docs.pikvm.org/webrtc") gop]:
tr.feature-disabled#stream-mode
+menu_radio_td2("stream-mode-radio", [
{title: "WebRTC", value: "janus"},
{title: "H.264", value: "media"},
{title: "MJPEG", value: "mjpeg", checked: true},
]) #[a(target="_blank" href="https://docs.pikvm.org/webrtc") Video mode]:
tr.feature-disabled#stream-orient
+menu_radio_td2("stream-orient-radio", [
{title: "Default", value: "0", checked: true},
{title: "90&deg;", value: "90"},
{title: "180&deg;", value: "180"},
{title: "270&deg;", value: "270"},
]) Orientation:
tr.feature-disabled#stream-audio
+menu_slider_td3("stream-audio-volume-slider", "stream-audio-volume-value") Audio volume:
tr.feature-disabled#stream-mic
+menu_switch_td2("stream-mic-switch", false, false) Microphone:
hr
div(class="buttons buttons-row")
button(data-force-hide-menu data-show-window="stream-window" class="row33") &bull; Show stream
button(data-force-hide-menu id="stream-screenshot-button" class="row33") &bull; Screenshot
button(id="stream-reset-button" class="row33") Reset stream
.buttons.buttons-row
button.row33(data-force-hide-menu data-show-window="stream-window") &bull; Show stream
button.row33#stream-screenshot-button(data-force-hide-menu) &bull; Screenshot
button.row33#stream-reset-button Reset stream
hr
table(class="kv")
tr(id="hid-outputs-keyboard", class="feature-disabled")
table.kv
tr.feature-disabled#hid-outputs-keyboard
td Keyboard mode:
td #[div(id="hid-outputs-keyboard-box" class="radio-box")]
tr(id="hid-outputs-mouse", class="feature-disabled")
td Mouse #[a(target="_blank" href="https://docs.pikvm.org/mouse") mode]:
td #[div(id="hid-outputs-mouse-box" class="radio-box")]
details
summary Keyboard &amp; mouse (HID) settings
div(class="spoiler")
table(class="kv")
tr
+menu_switch_notable("hid-keyboard-swap-cc-switch", "Swap Left Ctrl and Caps keys", true, false)
td #[div.radio-box#hid-outputs-keyboard-box]
tr.feature-disabled#hid-outputs-mouse
td #[a(target="_blank" href="https://docs.pikvm.org/mouse") Mouse mode]:
td #[div.radio-box#hid-outputs-mouse-box]
+menu_spoiler("Keyboard &amp; mouse (HID) settings")
+menu_switch_table("hid-keyboard-swap-cc-switch", true, false) Swap Left Ctrl and Caps keys:
hr
table(class="kv")
tr
td Mouse polling:
td(class="value-slider") #[input(type="range" id="hid-mouse-rate-slider" class="slider")]
td(id="hid-mouse-rate-value" class="value-number")
tr(id="hid-mouse-sens" class="feature-disabled")
td Relative sensitivity:
td(class="value-slider") #[input(disabled type="range" id="hid-mouse-sens-slider" class="slider")]
td(id="hid-mouse-sens-value" class="value-number")
+menu_slider_td3("hid-mouse-rate-slider", "hid-mouse-rate-value") Mouse polling:
tr.feature-disabled#hid-mouse-sens
+menu_slider_td3("hid-mouse-sens-slider", "hid-mouse-sens-value", false) Relative sensitivity:
tr(id="hid-mouse-squash" class="feature-disabled")
+menu_switch_notable("hid-mouse-squash-switch", "Squash relative moves", true, true)
+menu_switch_td2("hid-mouse-squash-switch", true, true) Squash relative moves:
tr
td Reverse scrolling:
td
table
tr
+menu_switch_notable("hid-mouse-reverse-scrolling-switch", "Y", true, false)
+menu_switch_td2("hid-mouse-reverse-scrolling-switch", true, false) Y:
td &nbsp;&nbsp;
+menu_switch_notable("hid-mouse-reverse-panning-switch", "X", true, false)
+menu_switch_td2("hid-mouse-reverse-panning-switch", true, false) X:
tr
+menu_switch_notable("hid-mouse-cumulative-scrolling-switch", "Cumulative scrolling", true, false)
+menu_switch_td2("hid-mouse-cumulative-scrolling-switch", true, false) Cumulative scrolling:
tr
td Scroll rate:
td(class="value-slider") #[input(type="range" id="hid-mouse-scroll-slider" class="slider")]
td(id="hid-mouse-scroll-value" class="value-number")
+menu_slider_td3("hid-mouse-scroll-slider", "hid-mouse-scroll-value") Scroll rate:
tr
+menu_switch_notable("hid-mouse-dot-switch", "Show the blue dot", true, true)
details
summary Web UI settings
div(class="spoiler")
table(class="kv")
+menu_switch_td2("hid-mouse-dot-switch", true, true) Show the blue dot:
+menu_spoiler("Web UI settings")
table.kv
tr
+menu_switch_notable("page-close-ask-switch", "Ask page close confirmation", true, true)
+menu_switch_td2("page-close-ask-switch", true, true) Ask page close confirmation:
tr
+menu_switch_notable("page-full-tab-stream-switch", "Expand for the entire tab by default", true, false)
table(class="kv")
+menu_switch_td2("page-full-tab-stream-switch", true, false) Expand for the entire tab by default:
table.kv
tr
+menu_switch_notable("hid-keyboard-bad-link-switch", "Bad link mode (release keys immediately)", true, false)
tr(id="hid-connect" class="feature-disabled")
+menu_switch_notable("hid-connect-switch", "Connect HID to Server", true, true)
tr(id="hid-jiggler" class="feature-disabled")
+menu_switch_notable("hid-jiggler-switch", "<a href=\"https://docs.pikvm.org/mouse_jiggler\" target=\"_blank\">Mouse jiggler</a>", false, false)
+menu_switch_td2("hid-keyboard-bad-link-switch", true, false) Bad link mode (release keys immediately):
tr.feature-disabled#hid-connect
+menu_switch_td2("hid-connect-switch", true, true) Connect HID to Server:
tr.feature-disabled#hid-jiggler
+menu_switch_td2("hid-jiggler-switch", false, false)
a(target="_blank" href="https://docs.pikvm.org/mouse_jiggler") Mouse jiggler:
tr
+menu_switch_notable("hid-mute-switch", "Mute all input HID events", true, false)
tr(id="v3-usb-breaker" class="feature-disabled")
+menu_switch_notable_gpio("__v3_usb_breaker__", "Connect main USB to Server",
"Turning off this switch will disconnect the main USB from the server. Are you sure you want to continue?")
tr(id="v4-locator" class="feature-disabled")
+menu_switch_notable_gpio("__v4_locator__", "Enable locator LED")
+menu_switch_td2("hid-mute-switch", true, false) Mute all input HID events:
tr.feature-disabled#v3-usb-breaker
+menu_switch_td2_gpio(
"__v3_usb_breaker__",
"Turning off this switch will disconnect the main USB from the server. Are you sure you want to continue?"
) Connect main USB to Server:
tr.feature-disabled#v4-locator
+menu_switch_td2_gpio("__v4_locator__") Enable locator LED:
hr
div(class="buttons buttons-row")
button(data-force-hide-menu data-show-window="keyboard-window" class="row50") &bull; Show keyboard
button(disabled id="hid-reset-button" class="row50") Reset HID
.buttons.buttons-row
button.row50(data-force-hide-menu data-show-window="keyboard-window") &bull; Show keyboard
button.row50#hid-reset-button(disabled) Reset HID

View File

@ -1,45 +1,43 @@
li(id="text-dropdown" class="right")
a(class="menu-button" href="#")
li.right#text-dropdown
a.menu-button(href="#")
+navbar_led("stream-ocr-led", "led-gear", "feature-disabled")
span Text
div(id="text-menu" class="menu")
div(class="text")
.menu#text-menu
.text
b Paste text as keypress sequence#[br]
sub Please note that PiKVM cannot switch the keyboard layout
hr
div(class="text" style="margin-right: 20px")
textarea(id="hid-pak-text" data-focus placeholder="Enter your text here")
table(class="kv")
.text(style="margin-right: 20px")
textarea#hid-pak-text(data-focus placeholder="Enter your text here")
table.kv
tr
td
button(disabled data-force-hide-menu id="hid-pak-button") &bull; Paste
td #[button#hid-pak-button(disabled data-force-hide-menu) &bull; Paste]
td using host keymap
td
select(id="hid-pak-keymap-selector")
table(class="kv")
td #[select#hid-pak-keymap-selector]
table.kv
tr
+menu_switch_notable("hid-pak-slow-switch", "Slow typing", true, false)
+menu_switch_td2("hid-pak-slow-switch", true, false) Slow typing:
tr
+menu_switch_notable("hid-pak-secure-switch", "Hide input text", true, false)
+menu_switch_td2("hid-pak-secure-switch", true, false) Hide input text:
tr
+menu_switch_notable("hid-pak-ask-switch", "Ask paste confirmation", true, true)
div(id="stream-ocr" class="feature-disabled")
+menu_switch_td2("hid-pak-ask-switch", true, true) Ask paste confirmation:
.feature-disabled#stream-ocr
hr
br
hr
div(class="text")
.text
b Text recognition <sup><i>&beta;</i></sup>#[br]
sub #[a(target="_blank" href="https://docs.pikvm.org/ocr") OCR] works locally on PiKVM
hr
table(class="kv")
table.kv
tr
td
button(data-force-hide-menu id="stream-ocr-button") &bull; Select area
td #[button#stream-ocr-button(data-force-hide-menu) &bull; Select area]
td for
td
select(id="stream-ocr-lang-selector")
td #[select#stream-ocr-lang-selector]
td text recognition
table(class="kv")
table.kv
tr
td(colspan="4") &bull; Press #[b Enter] to recognize and copy text to clipboard
tr

View File

@ -1,8 +1,9 @@
mixin navbar_led(id, icon, cls="led-gray")
img(id=id, class=cls src=`${svg_dir}/${icon}.svg`)
mixin menu_message(icon, short, classes="")
div(class="text")
.text
table
tr
td(rowspan="2") #[img(class=`sign ${classes}` src=`${svg_dir}/${icon}.svg`)]
@ -13,34 +14,77 @@ mixin menu_message(icon, short, classes="")
sup(style="line-height:1")
block
mixin menu_switch_notable_gpio(channel, title, confirm_off="")
td !{title}:
td(align="right")
div(class="switch-box")
input(disabled type="checkbox" id=`__gpio-switch-${channel}` class=`__gpio-switch-${channel} gpio-switch`
data-channel=channel data-confirm-off=confirm_off)
label(for=`__gpio-switch-${channel}`)
span(class="switch-inner")
span(class="switch")
mixin menu_switch_notable(id, title, enabled, checked)
td !{title}:
mixin menu_switch_td2_gpio(channel, confirm_off="")
td
block
td(align="right")
div(class="switch-box")
.switch-box
input(
disabled
type="checkbox"
id=`__gpio-switch-${channel}`
class=`__gpio-switch-${channel} gpio-switch`
data-channel=channel
data-confirm-off=confirm_off
)
label(for=`__gpio-switch-${channel}`)
span.switch-inner
span.switch
mixin menu_switch_td2(id, enabled, checked)
td
block
td(align="right")
.switch-box
input(checked=checked disabled=!enabled type="checkbox" id=id)
label(for=id)
span(class="switch-inner")
span(class="switch")
span.switch-inner
span.switch
mixin menu_switch(id, title, enabled, checked)
table(class="kv")
mixin menu_switch_table(id, enabled, checked)
table.kv
tr
+menu_switch_notable(id, title, enabled, checked)
+menu_switch_td2(id, enabled, checked)
block
ul(id="navbar")
li(class="left")
mixin menu_radio_td2(name, items)
td
block
td
.radio-box
each item in items
-
let id = `${name}-${item["value"]}`
let checked = (item["checked"] || false)
input(type="radio" id=id name=name value=item["value"] checked=checked)
label(for=id) !{item["title"]}
mixin menu_slider_td3(slider_id, value_id, enabled)
-
enabled = (enabled || true)
td
block
td.value-slider
input.slider(type="range" id=slider_id disabled=!enabled)
td.value-number(id=value_id)
mixin menu_spoiler(title)
details
summary !{title}
div(class="spoiler")
block
ul#navbar
li.left
a(id="logo" href="/") &larr;&nbsp;&nbsp;
img(class="svg-gray" src=`${svg_dir}/logo.svg` alt="&pi;-kvm")
img.svg-gray(src=`${svg_dir}/logo.svg` alt="&pi;-kvm")
include navbar-health.pug

View File

@ -2,47 +2,49 @@ mixin about_tab(name, title, checked=false)
- let button_id = `about-tab-${name}-button`
input(checked=checked type="radio" name="about-tab-button", id=button_id)
label(for=button_id) #{title}
div(class="tab")
div(id=`about-${name}` class="code")
.tab
.code(id=`about-${name}`)
if block
block
else
span(class="code-comment") No data
span.code-comment No data
div(id="about-window" class="window")
div(class="window-header")
div(class="window-grab") About
button(class="window-button-close") #[b &times;]
div(id="about")
.window#about-window
.window-header
.window-grab About
button.window-button-close #[b &times;]
#about
table
tr
td(class="logo")
td.logo
a(href="https://pikvm.org" target="_blank")
img(class="svg-gray" src=`${svg_dir}/logo.svg` alt="PiKVM" height="40")
img.svg-gray(src=`${svg_dir}/logo.svg` alt="PiKVM" height="40")
td
table
tr #[td(colspan="2" class="title") The Open Source KVM over IP]
tr
td(colspan="2" class="copyright")
td.title(colspan="2")
| The Open Source KVM over IP
tr
td.copyright(colspan="2")
| Copyright &copy; 2018-2024 #[a(target="_blank" href="mailto:mdevaev@gmail.com") Maxim Devaev]
br
div(class="tabs-box")
.tabs-box
+about_tab("meta", "Meta", true)
div
span(class="code-comment")
span.code-comment
| // You can get this JSON using handle #[a(target="_blank" href="/api/info?fields=meta") /api/info?fields=meta]#[br]
| // In the standard configuration this data#[br]
| // is specified in the file /etc/kvmd/meta.yaml
br
pre(id="kvmd-meta-json")
| No data
pre#kvmd-meta-json No data
+about_tab("hardware", "Hardware")
+about_tab("version", "Version")
+about_tab("thanks", "Thanks")
span(class="code-comment")
span.code-comment
| // These kind people donated money to the PiKVM project#[br]
| // and supported the work on it. We are very grateful#[br]
| // for their help, and memorializing their names#[br]
@ -690,7 +692,7 @@ div(id="about-window" class="window")
li Zoltan Magyari
li Zsombor Vari
br
p(class="text credits")
p.text.credits
a(target="_blank" href="https://pikvm.org") PiKVM Project
| &nbsp; | &nbsp;
a(target="_blank" href="https://docs.pikvm.org") Documentation

View File

@ -1,41 +1,43 @@
mixin key(spacer, code, classes="", width=0)
div(data-code=code, class=`key ${classes}`, style=(width ? `width:${width}px` : ""))
div(class="label")
block
if spacer == 1
div(class="spacer")
else if spacer == 2
div(class="spacer-fixed")
mixin spacer(sp)
if sp == 1
.spacer
else if sp == 2
.spacer-fixed
mixin modifier(spacer, code, classes="", width=0)
div(data-code=code class=`modifier ${classes}` style=(width ? `width:${width}px` : ""))
div(class="label")
mixin key(sp, code, classes="", width=0)
div(data-code=code, class=`key ${classes}`, style=(width ? `width: ${width}px` : ""))
.label
block
+spacer(sp)
mixin modifier(sp, code, classes="", width=0)
div(data-code=code class=`modifier ${classes}` style=(width ? `width: ${width}px` : ""))
.label
| #[b &bull;]#[br]
block
if spacer == 1
div(class="spacer")
else if spacer == 2
div(class="spacer-fixed")
+spacer(sp)
mixin empty(spacer, classes="", width=0)
mixin empty(sp, classes="", width=0)
div(class=`empty ${classes}` style=(width ? `width:${width}px` : ""))
div(class="label") &nbsp;
if spacer == 1
div(class="spacer")
else if spacer == 2
div(class="spacer-fixed")
.label &nbsp;
+spacer(sp)
mixin lamp(cls)
img(class=`inline-lamp-small ${cls} led-gray` src=`${svg_dir}/led-square.svg`)
div(id="keyboard-window" class="window")
div(id="keyboard-window-header" class="window-header")
div(class="window-grab") Virtual Keyboard
button(class="window-button-close") #[b &times;]
div(id="keyboard-desktop" class="keypad" align="center")
div(class="keypad-block")
div(class="keypad-row")
.window#keyboard-window
.window-header#keyboard-window-header
.window-grab Virtual Keyboard
button.window-button-close #[b &times;]
.keypad#keyboard-desktop(align="center")
.keypad-block
.keypad-row
+key(2, "Escape", "small") Esc
+empty(1, "", 24)
each key in ["F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12"]
@ -43,7 +45,7 @@ div(id="keyboard-window" class="window")
if key == "F4" || key == "F8"
+empty(1, "", 10)
hr
div(class="keypad-row")
.keypad-row
+key(1, "Backquote") ~#[br]`
each key, index in ["!", "@", "#", "$", "%", "^", "&", "*", "("]
+key(1, `Digit${index + 1}`) #{key}#[br]#{index + 1}
@ -51,14 +53,14 @@ div(id="keyboard-window" class="window")
+key(1, "Minus") _#[br]-
+key(1, "Equal") +#[br]=
+key(0, "Backspace", "wide-1 right") &#8612;
div(class="keypad-row")
.keypad-row
+key(1, "Tab", "wide-1 left") &#8676;#[br]&#8677;
each key in ["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"]
+key(1, `Key${key}`, "single") #{key}
+key(1, "BracketLeft") {#[br][
+key(1, "BracketRight") }#[br]]
+key(0, "Backslash") |#[br]&bsol;
div(class="keypad-row")
.keypad-row
+key(1, "CapsLock", "wide-2 left small")
+lamp("hid-keyboard-caps-led")
| #[br] Caps Lock
@ -67,7 +69,7 @@ div(id="keyboard-window" class="window")
+key(1, "Semicolon") :#[br];
+key(1, "Quote") "#[br]'
+key(0, "Enter", "wide-2 right small") Enter#[br]&crarr;
div(class="keypad-row")
.keypad-row
+modifier(1, "ShiftLeft", "wide-3 left small") Shift
each key in ["Z", "X", "C", "V", "B", "N", "M"]
+key(1, `Key${key}`, "single") #{key}
@ -75,7 +77,7 @@ div(id="keyboard-window" class="window")
+key(1, "Period") &gt;#[br].
+key(1, "Slash") ?#[br]/
+modifier(0, "ShiftRight", "wide-3 right small") Shift
div(class="keypad-row")
.keypad-row
+modifier(2, "ControlLeft", "wide-1 left small") Ctrl
+modifier(2, "MetaLeft", "wide-1 left small") Win
+modifier(2, "AltLeft", "wide-1 left small") Alt
@ -84,83 +86,83 @@ div(id="keyboard-window" class="window")
+modifier(2, "MetaRight", "wide-1 right small") Win
+key(2, "ContextMenu", "small") #[br]Menu
+modifier(0, "ControlRight", "wide-1 right small") Ctrl
div(class="keypad-block")
div(class="keypad-row")
.keypad-block
.keypad-row
+modifier(2, "PrintScreen", "small") Pt/Sq
+key(2, "ScrollLock", "small")
+lamp("hid-keyboard-scroll-led")
| #[br] ScrLk
+key(0, "Pause", "small") P/Brk
hr
div(class="keypad-row")
.keypad-row
+key(2, "Insert", "small") Ins
+key(2, "Home", "small") Home
+key(0, "PageUp", "small") PgUp
div(class="keypad-row")
.keypad-row
+key(2, "Delete", "small") Del
+key(2, "End", "small") End
+key(0, "PageDown", "small") PgDn
div(class="keypad-row")
div(class="keypad-row")
.keypad-row
.keypad-row
+empty(1, "")
+key(2, "ArrowUp") &uarr;
+empty(0, "")
div(class="keypad-row")
.keypad-row
+key(2, "ArrowLeft") &larr;
+key(2, "ArrowDown") &darr;
+key(0, "ArrowRight") &rarr;
div(class="keypad-block")
div(class="keypad-row")
.keypad-block
.keypad-row
+empty(2, "small")
+empty(2, "small")
+empty(2, "small")
+key(0, "Power", "small") PWR
hr
div(class="keypad-row")
.keypad-row
+key(2, "NumLock", "small")
+lamp("hid-keyboard-num-led")
| #[br] NmLk
+key(2, "NumpadDivide") /
+key(2, "NumpadMultiply") *
+key(0, "NumpadSubtract") -
div(class="keypad-row")
.keypad-row
+key(2, "Numpad7", "small") 7#[br]Home
+key(2, "Numpad8", "small") 8#[br]&uarr;
+key(2, "Numpad9", "small") 9#[br]PgUp
+empty(0, "")
div(class="keypad-row")
.keypad-row
+key(2, "Numpad4", "small") 4#[br]&larr;
+key(2, "Numpad5", "small") 5#[br]#[br]
+key(2, "Numpad6", "small") 6#[br]&rarr;
+key(0, "NumpadAdd") +
div(class="keypad-row")
.keypad-row
+key(2, "Numpad1", "small") 1#[br]End
+key(2, "Numpad2", "small") 2#[br]&darr;
+key(2, "Numpad3", "small") 3#[br]PgDn
+empty(0, "")
div(class="keypad-row")
.keypad-row
+key(2, "Numpad0", "small") 0#[br]Ins
+empty(2, "")
+key(2, "NumpadDecimal", "small") .#[br]Del
+key(0, "NumpadEnter", "small") Ent
div(class="keypad-block")
div(class="keypad-row")
.keypad-block
.keypad-row
+key(0, "IntlBackslash", "small") &bsol;#[br]|
hr
div(class="keypad-row")
.keypad-row
+key(0, "IntlYen", "small") ¥#[br]_
div(class="keypad-row")
.keypad-row
+key(0, "IntlRo", "small") &bsol;#[br]ろ
div(class="keypad-row")
.keypad-row
+modifier(0, "KanaMode", "small") Kana
div(class="keypad-row")
.keypad-row
+modifier(0, "NonConvert", "small") N/Cnv
div(class="keypad-row")
.keypad-row
+modifier(0, "Convert", "small") Cnv
div(id="keyboard-mobile" class="keypad" align="center")
div(class="keypad-block")
div(class="keypad-row")
.keypad#keyboard-mobile(align="center")
.keypad-block
.keypad-row
+key(1, "Escape", "small") Esc
+key(0, "F1", "wide-0 small rounded-left") F1
+key(0, "F2", "wide-0 small rounded-none") F2
@ -183,7 +185,7 @@ div(id="keyboard-window" class="window")
+key(1, "Home", "small") Home
+key(1, "End", "small") End
+key(0, "Delete", "small") Del
div(class="keypad-row")
.keypad-row
+key(1, "Backquote") ~#[br]`
each key, index in ["!", "@", "#", "$", "%", "^", "&", "*", "("]
+key(1, `Digit${index + 1}`) #{key}#[br]#{index + 1}
@ -191,14 +193,14 @@ div(id="keyboard-window" class="window")
+key(1, "Minus") _#[br]-
+key(1, "Equal") +#[br]=
+key(0, "Backspace", "wide-2 right", 101) &#8612;
div(class="keypad-row")
.keypad-row
+key(1, "Tab", "wide-1 left") &#8676;<br>&#8677;
each key in ["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"]
+key(1, `Key${key}`, "single") #{key}
+key(1, "BracketLeft") {#[br][
+key(1, "BracketRight") }#[br]]
+key(0, "Backslash", "wide-1 left", 78) |#[br]&bsol;
div(class="keypad-row")
.keypad-row
+key(1, "CapsLock", "wide-2 left small")
+lamp("hid-keyboard-caps-led")
| #[br] Caps Lock
@ -207,7 +209,7 @@ div(id="keyboard-window" class="window")
+key(1, "Semicolon") :#[br];
+key(1, "Quote") `#[br]'
+key(0, "Enter", "wide-3 right small", 116) Enter#[br]&crarr;
div(class="keypad-row")
.keypad-row
+modifier(1, "ShiftLeft", "wide-3 left small") Shift
each key in ["Z", "X", "C", "V", "B", "N", "M"]
+key(1, `Key${key}`, "single") #{key}
@ -217,7 +219,7 @@ div(id="keyboard-window" class="window")
+key(2, "PageUp", "small") PgUp
+key(2, "ArrowUp") &uarr;
+key(0, "PageDown", "small") PgDn
div(class="keypad-row")
.keypad-row
+modifier(1, "ControlLeft", "wide-1 left small") Ctrl
+modifier(1, "MetaLeft", "wide-1 left small") Win
+modifier(1, "AltLeft", "wide-1 left small") Alt

View File

@ -1,49 +1,50 @@
div(id="stream-ocr-window" class="window")
div(id="stream-ocr-selection" class="hidden")
.window#stream-ocr-window
.hidden#stream-ocr-selection
div(id="stream-window" class="window window-resizable")
div(id="stream-window-header" class="window-header")
div(class="window-grab") MJPEG
button(class="window-button-close") #[b &times;]
button(class="window-button-maximize") &#9744;
button(class="window-button-original") &bull;
button(class="window-button-enter-full-tab") &#9650;
button(class="window-button-full-screen") &#10530;
.window.window-resizable#stream-window
.window-header#stream-window-header
.window-grab MJPEG
button.window-button-close #[b &times;]
button.window-button-maximize &#9744;
button.window-button-original &bull;
button.window-button-enter-full-tab &#9650;
button.window-button-full-screen &#10530;
div(id="stream-info")
#stream-info
button(class="window-button-exit-full-tab") &#9660;
div(id="stream-box" class="stream-box-offline")
img(id="stream-image" src=`${png_dir}/blank-stream.png`)
video(id="stream-video" class="hidden" disablePictureInPicture="true" autoplay playsinline muted)
canvas(id="stream-canvas" class="hidden")
div(id="stream-fullscreen-active")
button.window-button-exit-full-tab &#9660;
div(id="stream-mouse-buttons" class="keypad" align="center")
div(class="keypad-block")
div(class="keypad-row")
div(data-code="left" class="key wide-3 left rounded-left")
div(class="label") Left
div(data-code="left" class="modifier left small rounded-right")
div(class="label") #[b &bull;]#[br]Hold
.stream-box-offline#stream-box
img#stream-image(src=`${png_dir}/blank-stream.png`)
video.hidden#stream-video(disablePictureInPicture="true" autoplay playsinline muted)
canvas.hidden#stream-canvas
#stream-fullscreen-active
div(class="empty" style="width:15px")
.keypad#stream-mouse-buttons(align="center")
.keypad-block
.keypad-row
.key.wide-3.left.rounded-left(data-code="left")
.label Left
.modifier.left.small.rounded-right(data-code="left")
.label #[b &bull;]#[br]Hold
div(data-code="middle" class="key wide-1 left rounded-left")
div(class="label") Mid
div(data-code="middle" class="modifier left small rounded-right")
div(class="label") #[b &bull;]#[br]Hold
.empty(style="width: 15px")
div(class="empty" style="width:15px")
.key.wide-1.left.rounded-left(data-code="middle")
.label Mid
.modifier.left.small.rounded-right(data-code="middle")
.label #[b &bull;]#[br]Hold
div(data-code="right" class="modifier right small rounded-left")
div(class="label") #[b &bull;]#[br]Hold
div(data-code="right" class="key wide-3 right rounded-right")
div(class="label") Right
.empty(style="width: 15px")
div(class="empty" style="width:30px")
.modifier.right.small.rounded-left(data-code="right")
.label #[b &bull;]#[br]Hold
.key.wide-3.right.rounded-right(data-code="right")
.label Right
div(data-code="up" class="key small rounded-left")
div(class="label") Up
div(data-code="down" class="key small rounded-right")
div(class="label") Down
.empty(style="width: 30px")
.key.small.rounded-left(data-code="up")
.label Up
.key.small.rounded-right(data-code="down")
.label Down

View File

@ -1,95 +1,68 @@
mixin switch_tab(name, title, checked=false)
- let button_id = `switch-tab-${name}-button`
input(checked=checked type="radio" name="switch-tab-button", id=button_id)
input(checked=checked type="radio" name="switch-tab-button" id=button_id)
label(for=button_id) #{title}
div(class="tab")
.tab
block
div(id="switch-window" class="window" style="width:min-content")
div(class="window-header")
div(class="window-grab") Switch settings
button(class="window-button-close") #[b &times;]
div(class="tabs-box")
mixin color_slider_tr(name, title)
tr
td(style="white-space: nowrap") #{title}:
td #[input(type="color" id=`switch-color-${name}-input`)]
td #[input(type="range" id=`switch-color-${name}-brightness-slider` style="min-width: 150px")]
td &nbsp;&nbsp;&nbsp;
td #[button(id=`switch-color-${name}-default-button` class="small" title="Reset default") &#8635;]
.window#switch-window(style="width: min-content")
.window-header
.window-grab Switch settings
button.window-button-close #[b &times;]
.tabs-box
+switch_tab("edid", "EDIDs collection", true)
table
tr
td(colspan="2")
select(id="switch-edid-selector" size="8")
td(rowspan="2" style="vertical-align:top")
table(class="kv")
select#switch-edid-selector(size="8")
td(rowspan="2" style="vertical-align: top")
table.kv
tr
td Manufacturer:
td(id="switch-edid-info-mfc-id" class="value")
td.value#switch-edid-info-mfc-id
tr
td Product ID:
td(id="switch-edid-info-product-id" class="value")
td.value#switch-edid-info-product-id
tr
td Serial:
td(id="switch-edid-info-serial" class="value")
td.value#switch-edid-info-serial
tr
td Monitor name:
td(id="switch-edid-info-monitor-name" class="value")
td.value#switch-edid-info-monitor-name
tr
td Extra serial:
td(id="switch-edid-info-monitor-serial" class="value")
td.value#switch-edid-info-monitor-serial
tr
td Audio enabled:
td(id="switch-edid-info-audio" class="value")
td.value#switch-edid-info-audio
tr
td Data:
td #[button(disabled id="switch-edid-copy-data-button" class="small") Copy]
td #[button.small#switch-edid-copy-data-button(disabled) Copy]
tr
td #[button(id="switch-edid-add-button") Add new]
td(style="float:right") #[button(disabled id="switch-edid-remove-button") Remove]
td #[button#switch-edid-add-button Add new]
td(style="float: right") #[button#switch-edid-remove-button(disabled) Remove]
+switch_tab("colors", "Color scheme")
table
//tr
td Role
td Color
td Brightness
td
td Reset
//tr
td #[hr]
td #[hr]
td #[hr]
td
td #[hr]
tr
td(style="white-space: nowrap") Selected port:
td #[input(type="color" id="switch-color-active-input")]
td #[input(type="range" id="switch-color-active-brightness-slider" style="min-width:150px")]
td &nbsp;&nbsp;&nbsp;
td #[button(id="switch-color-active-default-button" class="small" title="Reset default") &#8635;]
tr
td(style="white-space: nowrap") Inactive port:
td #[input(type="color" id="switch-color-inactive-input")]
td #[input(type="range" id="switch-color-inactive-brightness-slider" style="min-width:150px")]
td &nbsp;&nbsp;&nbsp;
td #[button(id="switch-color-inactive-default-button" class="small" title="Reset default") &#8635;]
tr
td(style="white-space: nowrap") Blinking beacon:
td #[input(type="color" id="switch-color-beacon-input")]
td #[input(type="range" id="switch-color-beacon-brightness-slider" style="min-width:150px")]
td &nbsp;&nbsp;&nbsp;
td #[button(id="switch-color-beacon-default-button" class="small" title="Reset default") &#8635;]
+color_slider_tr("active", "Selected port")
+color_slider_tr("inactive", "Inactive port")
+color_slider_tr("beacon", "Blinking beacon")
tr
td #[hr]
td #[hr]
td #[hr]
td
td #[hr]
tr
td(style="white-space: nowrap") Flashing downlink:
td #[input(type="color" id="switch-color-flashing-input")]
td #[input(type="range" id="switch-color-flashing-brightness-slider" style="min-width:150px")]
td &nbsp;&nbsp;&nbsp;
td #[button(id="switch-color-flashing-default-button" class="small" title="Reset default") &#8635;]
tr
td(style="white-space: nowrap") Bootloader mode:
td #[input(type="color" id="switch-color-bootloader-input")]
td #[input(type="range" id="switch-color-bootloader-brightness-slider" style="min-width:150px")]
td &nbsp;&nbsp;&nbsp;
td #[button(id="switch-color-bootloader-default-button" class="small" title="Reset default") &#8635;]
+color_slider_tr("flashing", "Flashing downlink")
+color_slider_tr("bootloader", "Bootloader mode")

View File

@ -1,8 +1,9 @@
div(id="webterm-window" class="window window-resizable" style="width: 640px; height: 480px")
div(class="window-header")
div(class="window-grab") Terminal
button(class="window-button-close") #[b &times;]
button(class="window-button-maximize") &#9744;
.window.window-resizable#webterm-window(style="width: 640px; height: 480px")
.window-header
.window-grab Terminal
button.window-button-close #[b &times;]
button.window-button-maximize &#9744;
// Терминал глючит из-за зажимаемой клавиши ESC для выхода
// button(class="window-button-full-screen") &#10530;
iframe(id="webterm-iframe" src="" style="width: 100%; height: 100%")
iframe#webterm-iframe(src="" style="width: 100%; height: 100%")

View File

@ -51,19 +51,19 @@
<tr>
<td>Username:&nbsp;</td>
<td>
<input type="text" id="user-input" autocapitalize="off">
<input id="user-input" type="text" autocapitalize="off">
</td>
</tr>
<tr>
<td>Password:&nbsp;</td>
<td>
<input type="password" id="passwd-input" autocapitalize="off">
<input id="passwd-input" type="password" autocapitalize="off">
</td>
</tr>
<tr>
<td>2FA code:&nbsp;</td>
<td>
<input type="text" id="code-input" placeholder="if enabled">
<input id="code-input" type="text" placeholder="if enabled">
</td>
</tr>
<tr>

View File

@ -1,33 +1,36 @@
extends ../base.pug
append vars
- title = "PiKVM Login"
- main_js = "login/main"
- css_list = css_list.concat(["window", "modal", "login/login"])
-
title = "PiKVM Login"
main_js = "login/main"
css_list = css_list.concat(["window", "modal", "login/login"])
block body
form(action="javascript:void(0)")
div(id="login-box")
div(id="login")
#login-box
#login
table
tr
td Username:&nbsp;
td #[input(type="text" id="user-input" autocapitalize="off")]
td #[input#user-input(type="text" autocapitalize="off")]
tr
td Password:&nbsp;
td #[input(type="password" id="passwd-input" autocapitalize="off")]
td #[input#passwd-input(type="password" autocapitalize="off")]
tr
td 2FA code:&nbsp;
td #[input(type="text" id="code-input" placeholder="if enabled")]
td #[input#code-input(type="text" placeholder="if enabled")]
tr
td(colspan=2)
hr
tr
td
td #[button(id="login-button" class="key" style="width:100%") Login]
td #[button.key#login-button(style="width:100%") Login]
ul(class="footer")
li(class="left")
ul.footer
li.left
| This site is actively using JavaScript.#[br]
| It doesn't contain ads, but is blocked by some ad filters.#[br]
| Please turn it off to continue and reload the page.

View File

@ -1,20 +1,23 @@
extends ../start.pug
append vars
- title = "PiKVM VNC Info"
- main_js = "vnc/main"
- index_link = true
-
title = "PiKVM VNC Info"
main_js = "vnc/main"
index_link = true
block start
p(class="text")
p.text
| This PiKVM device has running #[b kvmd-vnc] daemon and provides VNC access to the server.
p(class="text")
p.text
| #[b WARNING!] We strongly don't recommend you to use VNC in untrusted networks without
| enabled X.509 or TLS encryption. Otherwise your passwords are transmitted in a plain text
| over the network.
p(class="text")
p.text
| Your VNC client must support Tight JPEG compression and password authentication.
| #[a(href="https://tigervnc.org") TigerVNC] is a good choice.
| On Linux, this client will most likely be available for installation from the repository.
| It can also be called vncviewer.
div(id="vnc-text" class="code" style="max-height:200px")
.code#vnc-text(style="max-height:200px")