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 css_dir = "/share/css"
- var svg_dir = "/share/svg" var js_dir = "/share/js"
- var png_dir = "/share/png" 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 block vars
html(lang="en") html(lang="en")
head head
meta(charset="utf-8") meta(charset="utf-8")

View File

@ -1,45 +1,48 @@
extends start.pug extends start.pug
append vars append vars
- title = "PiKVM Index" -
- main_js = "index/main" title = "PiKVM Index"
- css_list = css_list.concat(["window", "modal", "index/index"]) main_js = "index/main"
css_list = css_list.concat(["window", "modal", "index/index"])
block start block start
table table
tr tr
td(class="logo") td.logo
a(href="https://pikvm.org" target="_blank") 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 td
table 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 tr
td(colspan="2" class="copyright") td.copyright(colspan="2")
| Copyright © 2018-2024 #[a(target="_blank" href="mailto:mdevaev@gmail.com") Maxim Devaev] | Copyright © 2018-2024 #[a(target="_blank" href="mailto:mdevaev@gmail.com") Maxim Devaev]
hr hr
table table
td(class="server") td(class="server")
td 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 hr
div(id="apps-box") #apps-box
h4 Loading ... h4 Loading ...
div(id="app-keyboard-warning") #app-keyboard-warning
hr hr
p(class="text") p.text
| Please note that when you are working with a KVM session or another application that captures the keyboard, | 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). | 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] | 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. | or #[a(target="_blank" href="https://chromium.org/Home") Chromium] in application mode.
div(id="app-text" class="code") .code#app-text
hr hr
p(class="text credits") p.text.credits
a(target="_blank" href="https://pikvm.org") PiKVM Project a(target="_blank" href="https://pikvm.org") PiKVM Project
|   |   |   |  
a(target="_blank" href="https://docs.pikvm.org") Documentation a(target="_blank" href="https://docs.pikvm.org") Documentation

View File

@ -1,20 +1,23 @@
extends ../start.pug extends ../start.pug
append vars append vars
- title = "PiKVM IPMI Info" -
- main_js = "ipmi/main" title = "PiKVM IPMI Info"
- index_link = true main_js = "ipmi/main"
index_link = true
block start 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 | 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. | 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 | #[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 | 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, | that the server send a salted SHA1 or MD5 hash of the requested user's password to the client,
| prior to the client authenticating. | 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. | #[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: | 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")

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -1,32 +1,34 @@
div(id="hw-health-dropdown" class="hidden") .hidden#hw-health-dropdown
li(class="left") li.left
a(class="menu-button" href="#") a.menu-button(href="#")
+navbar_led("hw-health-undervoltage-led", "led-undervoltage", "hidden") +navbar_led("hw-health-undervoltage-led", "led-undervoltage", "hidden")
+navbar_led("hw-health-overheating-led", "led-overheating", "hidden") +navbar_led("hw-health-overheating-led", "led-overheating", "hidden")
div(class="menu")
.menu
+menu_message("warning", "Raspberry Pi's health is at risk") +menu_message("warning", "Raspberry Pi's health is at risk")
| This is not a drill! A red icon indicates a current issue,#[br] | This is not a drill! A red icon indicates a current issue,#[br]
| a yellow one that was observed since the device booted up | 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 hr
+menu_message("led-undervoltage", "Undervoltage detected", "led-gray") +menu_message("led-undervoltage", "Undervoltage detected", "led-gray")
| Make sure your power supply and cabling are providing#[br] | Make sure your power supply and cabling are providing#[br]
| enough power to the Raspberry Pi (3A minimum) | enough power to the Raspberry Pi (3A minimum)
div(id="hw-health-message-overheating" class="hidden") .hidden#hw-health-message-overheating
hr hr
+menu_message("led-overheating", "Overheating detected", "led-gray") +menu_message("led-overheating", "Overheating detected", "led-gray")
| Frequency capping due to overheating,#[br] | Frequency capping due to overheating,#[br]
| please improve cooling of the Raspberry Pi | please improve cooling of the Raspberry Pi
div(id="fan-health-dropdown" class="hidden") .hidden#fan-health-dropdown
li(class="left") li.left
a(class="menu-button" href="#") a.menu-button(href="#")
+navbar_led("fan-health-led", "led-fan", "hidden") +navbar_led("fan-health-led", "led-fan", "hidden")
div(class="menu")
.menu
+menu_message("warning", "Raspberry Pi's health is at risk") +menu_message("warning", "Raspberry Pi's health is at risk")
| This is not a drill! A red icon indicates a current issue,#[br] | This is not a drill! A red icon indicates a current issue,#[br]
| a yellow one that was observed in the past | a yellow one that was observed in the past
div(id="fan-health-message-fail") #fan-health-message-fail
hr hr
+menu_message("led-fan", "Fan failed", "led-gray") +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] | 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") li.right#macro-dropdown
a(class="menu-button" href="#") a.menu-button(href="#")
+navbar_led("hid-recorder-led", "led-gear") +navbar_led("hid-recorder-led", "led-gear")
span Macro span Macro
div(class="menu")
div(class="text") .menu
.text
b Record and play HID/ATX/GPIO actions#[br] b Record and play HID/ATX/GPIO actions#[br]
sub For security reasons, the record will not be saved on the PiKVM sub For security reasons, the record will not be saved on the PiKVM
hr hr
div(class="buttons buttons-row")
button(disabled data-force-hide-menu id="hid-recorder-record" class="row25") • Rec .buttons.buttons-row
button(disabled id="hid-recorder-stop" class="row25") Stop button.row25#hid-recorder-record(disabled data-force-hide-menu) • Rec
button(disabled id="hid-recorder-play" class="row25") Play button.row25#hid-recorder-stop(disabled) Stop
button(disabled id="hid-recorder-clear" class="row25") Clear button.row25#hid-recorder-play(disabled) Play
button.row25#hid-recorder-clear(disabled) Clear
hr hr
table(class="kv")
table.kv
tr tr
td Script time: 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 tr
td Scripted events: td Scripted events:
td(id="hid-recorder-events-count" class="value") 0 td.value#hid-recorder-events-count 0
td #[sup #[i include delays]] td #[sup #[i include delays]]
hr 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 hr
input(type="file" id="hid-recorder-new-script-file")
div(class="buttons buttons-row") input#hid-recorder-new-script-file(type="file")
button(disabled id="hid-recorder-upload" class="row50") Upload script
button(disabled id="hid-recorder-download" class="row50") Download script .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") li.right.feature-disabled#msd-dropdown
a(class="menu-button" href="#") a.menu-button(href="#")
+navbar_led("msd-led", "led-msd") +navbar_led("msd-led", "led-msd")
span Drive span Drive
div(id="msd-menu" class="menu")
div(class="text") .menu#msd-menu
.text
b Mass Storage Drive: b Mass Storage Drive:
span(id="msd-status") span#msd-status
br br
hr hr
div(id="msd-message-offline" class="hidden")
.hidden#msd-message-offline
+menu_message("warning", "Mass Storage Drive is offline") +menu_message("warning", "Mass Storage Drive is offline")
hr hr
div(id="msd-message-image-broken" class="hidden") .hidden#msd-message-image-broken
+menu_message("warning", "Current image is broken!") +menu_message("warning", "Current image is broken!")
| Perhaps uploading was interrupted#[br] | Perhaps uploading was interrupted
hr 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!") +menu_message("warning", "Current image is too big for DVD!")
| The maximum is 31.6GiB. Please switch to the Flash mode. | The maximum is 31.6GiB. Please switch to the Flash mode.
hr 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") +menu_message("warning", "Current image is out of storage")
| This image was connected manually using #[b kvmd-otgmsd] | This image was connected manually using #[b kvmd-otgmsd]
hr hr
div(id="msd-message-rw-enabled" class="hidden") .hidden#msd-message-rw-enabled
+menu_message("warning", "Read-write mode is enabled") +menu_message("warning", "Read-write mode is enabled")
| Do not turn off PiKVM while this is active to prevent#[br] | Do not turn off PiKVM while this is active to prevent#[br]
| filesystem corruption. Use read-only mode where possible,#[br] | filesystem corruption. Use read-only mode where possible,#[br]
| as writing to SD card often can reduce its lifespan. | as writing to SD card often can reduce its lifespan.
hr hr
div(id="msd-message-downloads" class="hidden") .hidden#msd-message-downloads
+menu_message("info", "The image is being downloaded from PiKVM") +menu_message("info", "The image is being downloaded from PiKVM")
| Please wait | Please wait
hr hr
table(class="kv")
table.kv
tr tr
td Image: td Image:
td(width="100%") #[select(disabled id="msd-image-selector")] td(width="100%") #[select#msd-image-selector(disabled)]
td #[button(disabled id="msd-download-button" title="Download image") #[b   ⇩  ]] td #[button#msd-download-button(disabled title="Download image") #[b   ⇩  ]]
td #[button(disabled id="msd-remove-button" title="Remove image") #[b   ×  ]] td #[button#msd-remove-button(disabled title="Remove image") #[b   ×  ]]
table(class="kv")
table.kv
tr tr
td Drive #[a(target="_blank" href="https://docs.pikvm.org/msd") mode]: +menu_radio_td2("msd-mode-radio", [
td {title: "CD/DVD", value: "1", checked: true},
div(class="radio-box") {title: "Flash", value: "0"},
input(checked type="radio" id="msd-mode-radio-cdrom" name="msd-mode-radio" value="1") ]) Drive #[a(target="_blank" href="https://docs.pikvm.org/msd") mode]:
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
td   td  
+menu_switch_notable("msd-rw-switch", "Writable", false, false) +menu_switch_td2("msd-rw-switch", false, false) Writable:
hr hr
div(id="msd-storages")
#msd-storages
hr hr
div(class="buttons buttons-row")
button(disabled id="msd-select-new-button" class="row50") Select image to upload .buttons.buttons-row
button(disabled id="msd-upload-new-button" class="row25") Upload button.row50#msd-select-new-button(disabled) Select image to upload
button(disabled id="msd-abort-new-button" class="row25") Abort button.row25#msd-upload-new-button(disabled) Upload
div(id="msd-message-another-user-uploads" class="hidden") button.row25#msd-abort-new-button(disabled) Abort
hr hr
.hidden#msd-message-another-user-uploads
+menu_message("info", "Another user uploads an image") +menu_message("info", "Another user uploads an image")
div(id="msd-new-sub" class="hidden")
hr hr
table(class="kv")
.hidden#msd-new-sub
table.kv
tr tr
td Specify a local file: td Specify a local file:
td #[input(type="file" id="msd-new-file")] td #[input#msd-new-file(type="file")]
tr tr
td #[b Or] paste a URL: td #[b Or] paste a URL:
td #[input(type="text" id="msd-new-url" style="width: 100%")] td #[input#msd-new-url(type="text" style="width: 100%")]
tr(id="msd-new-part" class="hidden") tr.hidden#msd-new-part
td Upload partition: td Upload partition:
td(width="100%") #[select(id="msd-new-part-selector")] td(width="100%") #[select#msd-new-part-selector]
div(id="msd-uploading-sub" class="hidden")
hr hr
table(class="kv")
.hidden#msd-uploading-sub
table.kv
tr tr
td New image: td New image:
td(id="msd-uploading-name" class="value") td.value#msd-uploading-name
tr tr
td Upload size: td Upload size:
td(id="msd-uploading-size" class="value") td.value#msd-uploading-size
div(class="text") .text
div(id="msd-uploading-progress" class="progress") .progress#msd-uploading-progress
span(id="msd-uploading-progress-value" class="progress-value") span.progress-value#msd-uploading-progress-value
div(id="msd-new-tips" class="hidden")
hr hr
table(class="kv")
.hidden#msd-new-tips
table.kv
tr tr
td(class="value") Note: td.value Note:
td • Don't close the browser page until the upload is complete. td • Don't close the browser page until the upload is complete.
tr tr
td td
td • To speed up the upload, close the stream window. td • To speed up the upload, close the stream window.
hr hr
div(class="buttons buttons-row")
button(disabled id="msd-connect-button" class="row50") Connect drive to Server .buttons.buttons-row
button(disabled id="msd-disconnect-button" class="row25") Disconnect button.row50#msd-connect-button Connect drive to Server
button(disabled id="msd-reset-button" class="row25") Reset button.row25#msd-disconnect-button Disconnect
button.row25#msd-reset-button Reset

View File

@ -1,47 +1,51 @@
li(id="shortcuts-dropdown" class="right") li.right#shortcuts-dropdown
a(class="menu-button" href="#") Shortcuts a.menu-button(href="#") Shortcuts
div(id="shortcuts-menu" class="menu")
div(class="text") .menu#shortcuts-menu
.text
b Quick keyboard shortcuts#[br] b Quick keyboard shortcuts#[br]
sub Also see #[i System → Show keyboard] sub Also see #[i System → Show keyboard]
hr hr
div(class="buttons")
div(class="buttons-row") .buttons
button(data-force-hide-menu data-shortcut="CapsLock" class="row50") .buttons-row
button.row50(data-force-hide-menu data-shortcut="CapsLock")
| • Caps Lock   | • Caps Lock  
img(class="inline-lamp-small hid-keyboard-caps-led led-gray" src=`${svg_dir}/led-square.svg`) img.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") • Left Win button.row50(data-force-hide-menu data-shortcut="MetaLeft") • Left Win
hr hr
div(class="buttons-row") .buttons-row
button(data-force-hide-menu data-shortcut="AltLeft ShiftLeft" class="row50") • Alt+Shift button.row50(data-force-hide-menu data-shortcut="AltLeft ShiftLeft") • Alt+Shift
button(data-force-hide-menu data-shortcut="ControlLeft KeyW" class="row50") • Ctrl+W button.row50(data-force-hide-menu data-shortcut="ControlLeft KeyW") • Ctrl+W
div(class="buttons-row") .buttons-row
button(data-force-hide-menu data-shortcut="ControlLeft ShiftLeft" class="row50") • Ctrl+Shift button.row50(data-force-hide-menu data-shortcut="ControlLeft ShiftLeft") • Ctrl+Shift
button(data-force-hide-menu data-shortcut="AltLeft Tab" class="row50") • Alt+Tab button.row50(data-force-hide-menu data-shortcut="AltLeft Tab") • Alt+Tab
div(class="buttons-row") .buttons-row
button(data-force-hide-menu data-shortcut="ShiftLeft ShiftRight" class="row50") • Shift+Shift button.row50(data-force-hide-menu data-shortcut="ShiftLeft ShiftRight") • Shift+Shift
button(data-force-hide-menu data-shortcut="AltLeft Enter" class="row50") • Alt+Enter button.row50(data-force-hide-menu data-shortcut="AltLeft Enter") • Alt+Enter
div(class="buttons-row") .buttons-row
button(data-force-hide-menu data-shortcut="MetaLeft Space" class="row50") • Win+Space button.row50(data-force-hide-menu data-shortcut="MetaLeft Space") • Win+Space
button(data-force-hide-menu data-shortcut="AltLeft F4" class="row50") • Alt+F4 button.row50(data-force-hide-menu data-shortcut="AltLeft F4") • Alt+F4
hr hr
div(class="buttons-row") .buttons-row
button(data-force-hide-menu data-shortcut="ControlLeft AltLeft F1" class="row50") • Ctrl+Alt+F1 button.row50(data-force-hide-menu data-shortcut="ControlLeft AltLeft F1") • Ctrl+Alt+F1
button(data-force-hide-menu data-shortcut="MetaLeft KeyL" class="row50") • Win+L button.row50(data-force-hide-menu data-shortcut="MetaLeft KeyL") • Win+L
div(class="buttons-row") .buttons-row
button(data-force-hide-menu data-shortcut="ControlLeft AltLeft F2" class="row50") • Ctrl+Alt+F2 button.row50(data-force-hide-menu data-shortcut="ControlLeft AltLeft F2") • Ctrl+Alt+F2
button(data-force-hide-menu data-shortcut="PrintScreen" class="row50") • Print Screen button.row50(data-force-hide-menu data-shortcut="PrintScreen") • Print Screen
hr hr
div(class="buttons-row") .buttons-row
button(data-force-hide-menu data-shortcut="ControlLeft AltLeft Delete" class="row50") • Ctrl+Alt+Del button.row50(data-force-hide-menu data-shortcut="ControlLeft AltLeft Delete") • Ctrl+Alt+Del
button(data-force-hide-menu data-shortcut="Power" class="row50") • Power button.row50(data-force-hide-menu data-shortcut="Power") • Power
hr hr
div(class="text")
.text
| &darr; &bull; Alt+SysRq+... <sup><i>linux magic | &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> | #[a(target="_blank" href="https://www.kernel.org/doc/html/latest/admin-guide/sysrq.html") help]</i></sup>
hr hr
div(class="buttons")
div(class="buttons-row") .buttons
.buttons-row
- -
let sysrq = { let sysrq = {
"F": "Call the OOM killer to kill a memory hog process", "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", "T": "Dump a list of current tasks and their information to the console",
} }
each title, key in sysrq 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 hr
div(class="buttons-row") .buttons-row
- -
sysrq = { sysrq = {
"R": "Turn off keyboard raw mode, set it to XLATE", "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", "B": "Immediately reboot the system without syncing or unmounting disks",
} }
each title, key in sysrq 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 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") li.right.feature-disabled#switch-dropdown
a(class="menu-button" id="switch-menu-button" href="#") a.menu-button#switch-menu-button(href="#")
+navbar_led("switch-atx-power-led", "led-atx-power") +navbar_led("switch-atx-power-led", "led-atx-power")
+navbar_led("switch-atx-hdd-led", "led-atx-hdd") +navbar_led("switch-atx-hdd-led", "led-atx-hdd")
span Switch #[i #[sub(id="switch-active-port") ]] span Switch #[i #[sub#switch-active-port]]
div(id="switch-menu" class="menu")
table(style="border-spacing: 0px;") .menu#switch-menu
table(style="border-spacing: 0px")
tr tr
td td
div(class="text") .text
b #[a(target="_blank" href="https://docs.pikvm.org/switch") PiKVM Switch] is attached#[br] 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 sub Select a port or perform any available action like ATX click
td td
div(class="text") .text
button(data-force-hide-menu data-show-window="switch-window" class="small") &bull; Settings button.small(data-force-hide-menu data-show-window="switch-window") &bull; Settings
hr 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") +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 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 hr
table(id="switch-chain" class="kv")
table.kv#switch-chain

View File

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

View File

@ -1,8 +1,9 @@
mixin navbar_led(id, icon, cls="led-gray") mixin navbar_led(id, icon, cls="led-gray")
img(id=id, class=cls src=`${svg_dir}/${icon}.svg`) img(id=id, class=cls src=`${svg_dir}/${icon}.svg`)
mixin menu_message(icon, short, classes="") mixin menu_message(icon, short, classes="")
div(class="text") .text
table table
tr tr
td(rowspan="2") #[img(class=`sign ${classes}` src=`${svg_dir}/${icon}.svg`)] 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") sup(style="line-height:1")
block 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) mixin menu_switch_td2_gpio(channel, confirm_off="")
td !{title}: td
block
td(align="right") 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) input(checked=checked disabled=!enabled type="checkbox" id=id)
label(for=id) label(for=id)
span(class="switch-inner") span.switch-inner
span(class="switch") span.switch
mixin menu_switch(id, title, enabled, checked)
table(class="kv") mixin menu_switch_table(id, enabled, checked)
table.kv
tr 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; 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 include navbar-health.pug

View File

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

View File

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

View File

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

View File

@ -1,95 +1,68 @@
mixin switch_tab(name, title, checked=false) mixin switch_tab(name, title, checked=false)
- let button_id = `switch-tab-${name}-button` - 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} label(for=button_id) #{title}
div(class="tab") .tab
block 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) +switch_tab("edid", "EDIDs collection", true)
table table
tr tr
td(colspan="2") td(colspan="2")
select(id="switch-edid-selector" size="8") select#switch-edid-selector(size="8")
td(rowspan="2" style="vertical-align:top") td(rowspan="2" style="vertical-align: top")
table(class="kv") table.kv
tr tr
td Manufacturer: td Manufacturer:
td(id="switch-edid-info-mfc-id" class="value") td.value#switch-edid-info-mfc-id
tr tr
td Product ID: td Product ID:
td(id="switch-edid-info-product-id" class="value") td.value#switch-edid-info-product-id
tr tr
td Serial: td Serial:
td(id="switch-edid-info-serial" class="value") td.value#switch-edid-info-serial
tr tr
td Monitor name: td Monitor name:
td(id="switch-edid-info-monitor-name" class="value") td.value#switch-edid-info-monitor-name
tr tr
td Extra serial: td Extra serial:
td(id="switch-edid-info-monitor-serial" class="value") td.value#switch-edid-info-monitor-serial
tr tr
td Audio enabled: td Audio enabled:
td(id="switch-edid-info-audio" class="value") td.value#switch-edid-info-audio
tr tr
td Data: 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 tr
td #[button(id="switch-edid-add-button") Add new] td #[button#switch-edid-add-button Add new]
td(style="float:right") #[button(disabled id="switch-edid-remove-button") Remove] td(style="float: right") #[button#switch-edid-remove-button(disabled) Remove]
+switch_tab("colors", "Color scheme") +switch_tab("colors", "Color scheme")
table table
//tr +color_slider_tr("active", "Selected port")
td Role +color_slider_tr("inactive", "Inactive port")
td Color +color_slider_tr("beacon", "Blinking beacon")
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;]
tr tr
td #[hr] td #[hr]
td #[hr] td #[hr]
td #[hr] td #[hr]
td td
td #[hr] td #[hr]
tr +color_slider_tr("flashing", "Flashing downlink")
td(style="white-space: nowrap") Flashing downlink: +color_slider_tr("bootloader", "Bootloader mode")
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;]

View File

@ -1,8 +1,9 @@
div(id="webterm-window" class="window window-resizable" style="width: 640px; height: 480px") .window.window-resizable#webterm-window(style="width: 640px; height: 480px")
div(class="window-header") .window-header
div(class="window-grab") Terminal .window-grab Terminal
button(class="window-button-close") #[b &times;] button.window-button-close #[b &times;]
button(class="window-button-maximize") &#9744; button.window-button-maximize &#9744;
// Терминал глючит из-за зажимаемой клавиши ESC для выхода // Терминал глючит из-за зажимаемой клавиши ESC для выхода
// button(class="window-button-full-screen") &#10530; // 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> <tr>
<td>Username:&nbsp;</td> <td>Username:&nbsp;</td>
<td> <td>
<input type="text" id="user-input" autocapitalize="off"> <input id="user-input" type="text" autocapitalize="off">
</td> </td>
</tr> </tr>
<tr> <tr>
<td>Password:&nbsp;</td> <td>Password:&nbsp;</td>
<td> <td>
<input type="password" id="passwd-input" autocapitalize="off"> <input id="passwd-input" type="password" autocapitalize="off">
</td> </td>
</tr> </tr>
<tr> <tr>
<td>2FA code:&nbsp;</td> <td>2FA code:&nbsp;</td>
<td> <td>
<input type="text" id="code-input" placeholder="if enabled"> <input id="code-input" type="text" placeholder="if enabled">
</td> </td>
</tr> </tr>
<tr> <tr>

View File

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

View File

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