Next (#1074)
|
|
@ -1,48 +1,29 @@
|
||||||
---
|
---
|
||||||
name: Support request
|
name: Support request
|
||||||
about: Need some help? Got an error message?
|
about: Ask for help with OliveTin
|
||||||
title: ""
|
title: ''
|
||||||
type: support
|
labels: ''
|
||||||
labels:
|
|
||||||
- "waiting-on-developer"
|
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**What seems to be the problem?!**
|
**What is the problem you are having?**
|
||||||
|
|
||||||
If you are getting an error message, then please copy/paste, or better, provide
|
|
||||||
a screenshot to show us exactly what is wrong.
|
|
||||||
|
|
||||||
**Can you provide a sosreport?**
|
**What OliveTin version are you running?**
|
||||||
|
|
||||||
A sosreport really helps us to help you, by providing critical information about your install. If you can generate a sosreport, please copy and paste the output here.
|
|
||||||
|
|
||||||
How to generate a sosreport: https://docs.olivetin.app/sosreport.html
|
**Can you provide Server Diagnostics?**
|
||||||
|
|
||||||
**What package/file/container did you use to install OliveTin?**
|
Server Diagnostics really helps us to help you, by providing critical information about your install. If you can generate Server Diagnostics, please copy and paste the output here.
|
||||||
|
|
||||||
eg: OliveTin-1234-x86_64.rpm
|
How to generate Server Diagnostics: https://docs.olivetin.app/troubleshooting/server-diagnostics.html
|
||||||
eg: Container from Dockerhub - please include the version number
|
|
||||||
|
|
||||||
**Your config.yaml**
|
|
||||||
|
|
||||||
```
|
**What is your config.yaml?**
|
||||||
Please copy-paste your config.yaml here
|
|
||||||
|
|
||||||
You don't need to include anything under "actions:" unless that is where your
|
|
||||||
error probably is.
|
|
||||||
```
|
|
||||||
|
|
||||||
**OliveTin logs**
|
**What are the OliveTin service logs showing?**
|
||||||
|
|
||||||
If possible, please copy and paste your OliveTin logs from when the error happened.
|
|
||||||
|
|
||||||
**Screenshot of WebDeveloper console logs**
|
**Screenshots (if appropriate)**
|
||||||
|
|
||||||
If you know how, and if you think it's relevant, a screenshot of the
|
|
||||||
WebDeveloper console from when you clicked a button is often really helpful.
|
|
||||||
|
|
||||||
**Anything else?**
|
|
||||||
|
|
||||||
Add any other context about the problem here.
|
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,12 @@ integration-tests/flakey-test-runs.jsonl
|
||||||
service/flakey-test-runs.log
|
service/flakey-test-runs.log
|
||||||
service/flakey-test-runs.jsonl
|
service/flakey-test-runs.jsonl
|
||||||
.vscode/
|
.vscode/
|
||||||
webui/
|
/webui/
|
||||||
server.log
|
server.log
|
||||||
OliveTin
|
OliveTin
|
||||||
integration-tests/configs/authRequireGuestsToLogin/sessions.yaml
|
integration-tests/configs/authRequireGuestsToLogin/sessions.yaml
|
||||||
webui
|
/webui
|
||||||
webui.dev
|
/webui.dev
|
||||||
sessions.yaml
|
sessions.yaml
|
||||||
docs/build/
|
docs/build/
|
||||||
build/
|
build/
|
||||||
|
|
|
||||||
|
|
@ -163,9 +163,13 @@ nfpms:
|
||||||
- src: var/openrc/OliveTin
|
- src: var/openrc/OliveTin
|
||||||
dst: /etc/init.d/OliveTin
|
dst: /etc/init.d/OliveTin
|
||||||
|
|
||||||
- src: webui/
|
# Avoid type: tree for apk — nfpm writes GNU base-256 modes for walked
|
||||||
dst: /var/www/olivetin/
|
# dirs (ModeDir), which apk-tools rejects (#761 / goreleaser/nfpm#1112).
|
||||||
type: tree
|
- src: webui/index.html
|
||||||
|
dst: /var/www/olivetin/index.html
|
||||||
|
|
||||||
|
- src: webui/assets/*
|
||||||
|
dst: /var/www/olivetin/assets/
|
||||||
|
|
||||||
- src: config.yaml
|
- src: config.yaml
|
||||||
dst: /etc/OliveTin/config.yaml
|
dst: /etc/OliveTin/config.yaml
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 12 KiB |
|
|
@ -0,0 +1,2 @@
|
||||||
|
custom-webui/
|
||||||
|
__pycache__/
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIGDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
include ../../screenshots.mk
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
listenAddressSingleHTTPFrontend: 0.0.0.0:11337
|
||||||
|
|
||||||
|
logLevel: "WARN"
|
||||||
|
checkForUpdates: false
|
||||||
|
showFooter: false
|
||||||
|
|
||||||
|
actions:
|
||||||
|
- title: date
|
||||||
|
shell: date
|
||||||
|
icon: clock
|
||||||
|
maxRate:
|
||||||
|
- limit: 3
|
||||||
|
duration: 5m
|
||||||
|
After Width: | Height: | Size: 57 KiB |
|
|
@ -0,0 +1,11 @@
|
||||||
|
[DEFAULT]
|
||||||
|
base_url = http://localhost:11337/
|
||||||
|
dir = .
|
||||||
|
width = 980
|
||||||
|
height = 620
|
||||||
|
post_script_sleep = 0.5
|
||||||
|
|
||||||
|
[max-rate]
|
||||||
|
url = .
|
||||||
|
name = maxRate
|
||||||
|
script = setup_max_rate.py
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Show blocked rate-limit log entries for the date action."""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
|
_START_ACTION_REPEATEDLY_JS = """
|
||||||
|
const done = arguments[arguments.length - 1];
|
||||||
|
const title = arguments[0];
|
||||||
|
const count = arguments[1];
|
||||||
|
|
||||||
|
function bindingIdForTitle(actionTitle) {
|
||||||
|
const button = document.querySelector('[title="' + actionTitle + '"]');
|
||||||
|
if (!button) {
|
||||||
|
throw new Error('Action button not found: ' + actionTitle);
|
||||||
|
}
|
||||||
|
return button.closest('.action-button').id.replace('actionButton-', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function uniqueTrackingId() {
|
||||||
|
if (window.isSecureContext && window.crypto?.randomUUID) {
|
||||||
|
return window.crypto.randomUUID();
|
||||||
|
}
|
||||||
|
return 'doc-screenshot-' + Date.now() + '-' + Math.random();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function startAndWait(actionTitle) {
|
||||||
|
const bindingId = bindingIdForTitle(actionTitle);
|
||||||
|
const trackingId = uniqueTrackingId();
|
||||||
|
const response = await window.client.startAction({
|
||||||
|
bindingId,
|
||||||
|
arguments: [],
|
||||||
|
uniqueTrackingId: trackingId,
|
||||||
|
});
|
||||||
|
const executionTrackingId = response.executionTrackingId || trackingId;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const result = await window.client.executionStatus({
|
||||||
|
executionTrackingId,
|
||||||
|
});
|
||||||
|
if (result.logEntry?.executionFinished) {
|
||||||
|
return result.logEntry;
|
||||||
|
}
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function startRepeatedly(actionTitle, runs) {
|
||||||
|
for (let i = 0; i < runs; i++) {
|
||||||
|
await startAndWait(actionTitle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
startRepeatedly(title, count).then(() => done(true)).catch((err) => done(String(err)));
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_dashboard(driver, timeout=15):
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: bool(d.find_element(By.TAG_NAME, "body").get_attribute("loaded-dashboard"))
|
||||||
|
)
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: d.execute_script("return !!window.client")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_rate_limited_logs(driver, timeout=20):
|
||||||
|
def ready(d):
|
||||||
|
try:
|
||||||
|
rows = d.find_elements(By.CSS_SELECTOR, ".logs-table tbody tr")
|
||||||
|
blocked = d.find_elements(By.CSS_SELECTOR, ".logs-table .status-blocked")
|
||||||
|
completed = d.find_elements(By.CSS_SELECTOR, ".logs-table .status-success")
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
return len(rows) >= 5 and len(blocked) >= 2 and len(completed) >= 3
|
||||||
|
|
||||||
|
WebDriverWait(driver, timeout).until(ready)
|
||||||
|
|
||||||
|
|
||||||
|
def run(driver):
|
||||||
|
_wait_for_dashboard(driver)
|
||||||
|
|
||||||
|
driver.execute_async_script(_START_ACTION_REPEATEDLY_JS, "date", 5)
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
driver.execute_script("window.location.href = '/logs'")
|
||||||
|
_wait_for_rate_limited_logs(driver)
|
||||||
|
|
||||||
|
time.sleep(0.2)
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
custom-webui/
|
||||||
|
__pycache__/
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIGDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
include ../../screenshots.mk
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
listenAddressSingleHTTPFrontend: 0.0.0.0:11337
|
||||||
|
|
||||||
|
logLevel: "WARN"
|
||||||
|
checkForUpdates: false
|
||||||
|
showFooter: false
|
||||||
|
|
||||||
|
actions:
|
||||||
|
- title: Check disk space
|
||||||
|
icon: disk
|
||||||
|
onclick: execution-dialog
|
||||||
|
shell: |
|
||||||
|
echo "Filesystem Size Used Avail Use% Mounted on"
|
||||||
|
echo "/dev/mapper/fedora_mindstorm-root 99G 82G 12G 88% /"
|
||||||
|
echo "Filesystem Size Used Avail Use% Mounted on"
|
||||||
|
echo "/dev/mapper/fedora_mindstorm-root 99G 82G 12G 88% /"
|
||||||
|
After Width: | Height: | Size: 39 KiB |
|
|
@ -0,0 +1,11 @@
|
||||||
|
[DEFAULT]
|
||||||
|
base_url = http://localhost:11337/
|
||||||
|
dir = .
|
||||||
|
width = 900
|
||||||
|
height = 620
|
||||||
|
post_script_sleep = 0.5
|
||||||
|
|
||||||
|
[popup-output-only]
|
||||||
|
url = .
|
||||||
|
name = popupOutputOnly
|
||||||
|
script = setup_popup_output_only.py
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Open the execution dialog for Check disk space."""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_body_attr(driver, attr, timeout=15):
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: bool(d.find_element(By.TAG_NAME, "body").get_attribute(attr))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_logs_page(driver, timeout=15):
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: "/logs/" in d.current_url and not d.current_url.rstrip("/").endswith("/logs")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_execution_complete(driver, timeout=15):
|
||||||
|
def finished(d):
|
||||||
|
try:
|
||||||
|
status = d.find_element(By.CSS_SELECTOR, ".execution-dialog-status").text
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
return "Still running" not in status and "Queued" not in status
|
||||||
|
|
||||||
|
WebDriverWait(driver, timeout).until(finished)
|
||||||
|
|
||||||
|
|
||||||
|
def run(driver):
|
||||||
|
_wait_for_body_attr(driver, "loaded-dashboard")
|
||||||
|
|
||||||
|
driver.find_element(By.CSS_SELECTOR, '[title="Check disk space"]').click()
|
||||||
|
|
||||||
|
_wait_for_logs_page(driver)
|
||||||
|
_wait_for_execution_complete(driver)
|
||||||
|
|
||||||
|
WebDriverWait(driver, 15).until(
|
||||||
|
lambda d: "fedora_mindstorm-root" in d.find_element(
|
||||||
|
By.CSS_SELECTOR, "#execution-results-popup .xterm-rows"
|
||||||
|
).text
|
||||||
|
)
|
||||||
|
|
||||||
|
time.sleep(0.2)
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
custom-webui/
|
||||||
|
__pycache__/
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIGDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
include ../../screenshots.mk
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
listenAddressSingleHTTPFrontend: 0.0.0.0:11337
|
||||||
|
|
||||||
|
logLevel: "WARN"
|
||||||
|
checkForUpdates: false
|
||||||
|
showFooter: false
|
||||||
|
|
||||||
|
actions:
|
||||||
|
- title: date
|
||||||
|
icon: clock
|
||||||
|
shell: date
|
||||||
|
After Width: | Height: | Size: 46 KiB |
|
|
@ -0,0 +1,11 @@
|
||||||
|
[DEFAULT]
|
||||||
|
base_url = http://localhost:11337/
|
||||||
|
dir = .
|
||||||
|
width = 980
|
||||||
|
height = 640
|
||||||
|
post_script_sleep = 0.5
|
||||||
|
|
||||||
|
[diagnostics]
|
||||||
|
url = /diagnostics
|
||||||
|
name = diagnostics
|
||||||
|
script = setup_diagnostics.py
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Open the diagnostics page from advanced_configuration/diagnostics.adoc."""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_diagnostics_page(driver, timeout=30):
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: d.execute_script("return !!window.client")
|
||||||
|
)
|
||||||
|
|
||||||
|
def ready(d):
|
||||||
|
try:
|
||||||
|
ssh_heading = d.find_element(
|
||||||
|
By.XPATH,
|
||||||
|
'//*[self::h2 or self::h3][contains(normalize-space(), "SSH")]',
|
||||||
|
)
|
||||||
|
server_diagnostics_heading = d.find_element(
|
||||||
|
By.XPATH,
|
||||||
|
'//*[self::h2 or self::h3][contains(normalize-space(), "Server Diagnostics")]',
|
||||||
|
)
|
||||||
|
key_value = d.find_element(
|
||||||
|
By.XPATH,
|
||||||
|
'//dt[contains(normalize-space(), "Found Key")]/following-sibling::dd[1]',
|
||||||
|
)
|
||||||
|
config_value = d.find_element(
|
||||||
|
By.XPATH,
|
||||||
|
'//dt[contains(normalize-space(), "Found Config")]/following-sibling::dd[1]',
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return all(
|
||||||
|
element.is_displayed()
|
||||||
|
for element in (
|
||||||
|
ssh_heading,
|
||||||
|
server_diagnostics_heading,
|
||||||
|
key_value,
|
||||||
|
config_value,
|
||||||
|
)
|
||||||
|
) and all(
|
||||||
|
element.text.strip() not in ("", "?")
|
||||||
|
for element in (key_value, config_value)
|
||||||
|
)
|
||||||
|
|
||||||
|
WebDriverWait(driver, timeout).until(ready)
|
||||||
|
|
||||||
|
|
||||||
|
def run(driver):
|
||||||
|
_wait_for_diagnostics_page(driver)
|
||||||
|
time.sleep(0.2)
|
||||||
2
docs/modules/ROOT/images/advanced_configuration/webui/hide-navigation/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
custom-webui/
|
||||||
|
__pycache__/
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIGDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
include ../../../screenshots.mk
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
---
|
||||||
|
listenAddressSingleHTTPFrontend: 0.0.0.0:11337
|
||||||
|
|
||||||
|
logLevel: "WARN"
|
||||||
|
checkForUpdates: false
|
||||||
|
showFooter: false
|
||||||
|
showNavigation: false
|
||||||
|
|
||||||
|
actions:
|
||||||
|
- title: Ping the Internet
|
||||||
|
icon: ping
|
||||||
|
shell: ping -c 1 127.0.0.1
|
||||||
|
- title: Check disk space
|
||||||
|
icon: disk
|
||||||
|
shell: df -h
|
||||||
|
- title: check dmesg logs
|
||||||
|
icon: logs
|
||||||
|
shell: dmesg | tail -n 1
|
||||||
|
- title: date
|
||||||
|
icon: clock
|
||||||
|
shell: date
|
||||||
|
- title: Run backup script
|
||||||
|
icon: backup
|
||||||
|
shell: echo backup
|
||||||
|
- title: Ping host
|
||||||
|
icon: ping
|
||||||
|
shell: ping -c 1 127.0.0.1
|
||||||
|
- title: Restart Docker Container
|
||||||
|
icon: restart
|
||||||
|
shell: echo restart
|
||||||
|
- title: Delete old backups
|
||||||
|
icon: ashtonished
|
||||||
|
shell: echo delete
|
||||||
|
- title: Get OliveTin Theme
|
||||||
|
icon: theme
|
||||||
|
shell: echo theme
|
||||||
|
- title: Setup easy SSH
|
||||||
|
icon: ssh
|
||||||
|
shell: echo ssh
|
||||||
|
- title: Restart httpd on server1
|
||||||
|
icon: restart
|
||||||
|
shell: echo restart httpd
|
||||||
|
- title: Toggle GPIO light
|
||||||
|
icon: light
|
||||||
|
shell: echo toggle
|
||||||
|
- title: Run Automation Playbook
|
||||||
|
icon: robot
|
||||||
|
shell: echo ansible
|
||||||
|
After Width: | Height: | Size: 57 KiB |
|
|
@ -0,0 +1,11 @@
|
||||||
|
[DEFAULT]
|
||||||
|
base_url = http://localhost:11337/
|
||||||
|
dir = .
|
||||||
|
width = 1180
|
||||||
|
height = 760
|
||||||
|
post_script_sleep = 0.5
|
||||||
|
|
||||||
|
[hide-navigation]
|
||||||
|
url = .
|
||||||
|
name = hide-navigation
|
||||||
|
script = setup_hide_navigation.py
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Capture the Actions view with navigation hidden."""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
|
|
||||||
|
def run(driver):
|
||||||
|
WebDriverWait(driver, 15).until(
|
||||||
|
lambda d: bool(d.find_element(By.TAG_NAME, "body").get_attribute("loaded-dashboard"))
|
||||||
|
)
|
||||||
|
WebDriverWait(driver, 15).until(
|
||||||
|
lambda d: len(d.find_elements(By.ID, "mainnav")) == 0
|
||||||
|
)
|
||||||
|
WebDriverWait(driver, 15).until(
|
||||||
|
lambda d: len(d.find_elements(By.CSS_SELECTOR, ".action-button button")) >= 8
|
||||||
|
)
|
||||||
|
time.sleep(0.2)
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
custom-webui/
|
||||||
|
__pycache__/
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIGDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
include ../../../screenshots.mk
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
---
|
||||||
|
listenAddressSingleHTTPFrontend: 0.0.0.0:11337
|
||||||
|
|
||||||
|
logLevel: "WARN"
|
||||||
|
checkForUpdates: false
|
||||||
|
showFooter: false
|
||||||
|
|
||||||
|
pageTitle: My OliveTin Instance
|
||||||
|
|
||||||
|
actions:
|
||||||
|
- title: Ping the Internet
|
||||||
|
icon: ping
|
||||||
|
shell: ping -c 1 127.0.0.1
|
||||||
|
- title: Check disk space
|
||||||
|
icon: disk
|
||||||
|
shell: df -h /
|
||||||
|
- title: check dmesg logs
|
||||||
|
icon: logs
|
||||||
|
shell: dmesg | tail -n 1
|
||||||
|
After Width: | Height: | Size: 4.8 KiB |
|
|
@ -0,0 +1,11 @@
|
||||||
|
[DEFAULT]
|
||||||
|
base_url = http://localhost:11337/
|
||||||
|
dir = .
|
||||||
|
width = 980
|
||||||
|
height = 220
|
||||||
|
post_script_sleep = 0.5
|
||||||
|
|
||||||
|
[page-title]
|
||||||
|
url = .
|
||||||
|
name = page-title
|
||||||
|
script = setup_page_title.py
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Capture the custom page title from advanced_configuration/webui.adoc."""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
|
|
||||||
|
def run(driver):
|
||||||
|
WebDriverWait(driver, 15).until(
|
||||||
|
lambda d: bool(d.find_element(By.TAG_NAME, "body").get_attribute("loaded-dashboard"))
|
||||||
|
)
|
||||||
|
WebDriverWait(driver, 15).until(
|
||||||
|
lambda d: "My OliveTin Instance" in d.find_element(By.CSS_SELECTOR, "header h1").text
|
||||||
|
)
|
||||||
|
WebDriverWait(driver, 15).until(
|
||||||
|
lambda d: d.find_element(By.CSS_SELECTOR, '[title="Ping the Internet"]').is_displayed()
|
||||||
|
)
|
||||||
|
time.sleep(0.2)
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
custom-webui/
|
||||||
|
__pycache__/
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIGDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
include ../../../screenshots.mk
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
---
|
||||||
|
listenAddressSingleHTTPFrontend: 0.0.0.0:11337
|
||||||
|
|
||||||
|
logLevel: "WARN"
|
||||||
|
checkForUpdates: false
|
||||||
|
showFooter: false
|
||||||
|
|
||||||
|
sectionNavigationStyle: sidebar
|
||||||
|
|
||||||
|
actions:
|
||||||
|
- title: Check disk space
|
||||||
|
icon: disk
|
||||||
|
shell: df -h /
|
||||||
|
- title: Setup easy SSH
|
||||||
|
icon: ssh
|
||||||
|
shell: echo ssh
|
||||||
|
- title: My Servers ping
|
||||||
|
icon: ping
|
||||||
|
shell: echo ping
|
||||||
|
- title: My Containers list
|
||||||
|
icon: disk
|
||||||
|
shell: echo list
|
||||||
|
|
||||||
|
dashboards:
|
||||||
|
- title: My Servers
|
||||||
|
contents:
|
||||||
|
- title: My Servers ping
|
||||||
|
- title: My Containers
|
||||||
|
contents:
|
||||||
|
- title: My Containers list
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
[DEFAULT]
|
||||||
|
base_url = http://localhost:11337/
|
||||||
|
dir = .
|
||||||
|
width = 980
|
||||||
|
height = 520
|
||||||
|
post_script_sleep = 0.5
|
||||||
|
|
||||||
|
[sidebar]
|
||||||
|
url = .
|
||||||
|
name = sidebar
|
||||||
|
script = setup_sidebar.py
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Capture the default sidebar navigation style."""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_sidebar_navigation(driver, timeout=30):
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: bool(d.find_element(By.TAG_NAME, "body").get_attribute("loaded-dashboard"))
|
||||||
|
)
|
||||||
|
|
||||||
|
driver.find_element(By.ID, "sidebar-toggler-button").click()
|
||||||
|
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: d.find_element(By.ID, "mainnav").is_displayed()
|
||||||
|
)
|
||||||
|
|
||||||
|
driver.find_element(By.CSS_SELECTOR, "#mainnav .stick-toggle").click()
|
||||||
|
|
||||||
|
def ready(d):
|
||||||
|
try:
|
||||||
|
my_servers = d.find_element(
|
||||||
|
By.XPATH,
|
||||||
|
'//*[@id="mainnav"]//a[contains(normalize-space(), "My Servers")]',
|
||||||
|
)
|
||||||
|
my_containers = d.find_element(
|
||||||
|
By.XPATH,
|
||||||
|
'//*[@id="mainnav"]//a[contains(normalize-space(), "My Containers")]',
|
||||||
|
)
|
||||||
|
disk_space = d.find_element(By.CSS_SELECTOR, '[title="Check disk space"]')
|
||||||
|
ssh = d.find_element(By.CSS_SELECTOR, '[title="Setup easy SSH"]')
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
return all(element.is_displayed() for element in (my_servers, my_containers, disk_space, ssh))
|
||||||
|
|
||||||
|
WebDriverWait(driver, timeout).until(ready)
|
||||||
|
|
||||||
|
|
||||||
|
def run(driver):
|
||||||
|
_wait_for_sidebar_navigation(driver)
|
||||||
|
time.sleep(0.2)
|
||||||
|
After Width: | Height: | Size: 29 KiB |
|
|
@ -0,0 +1,2 @@
|
||||||
|
custom-webui/
|
||||||
|
__pycache__/
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIGDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
include ../../../screenshots.mk
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
---
|
||||||
|
listenAddressSingleHTTPFrontend: 0.0.0.0:11337
|
||||||
|
|
||||||
|
logLevel: "WARN"
|
||||||
|
checkForUpdates: false
|
||||||
|
showFooter: false
|
||||||
|
|
||||||
|
sectionNavigationStyle: topbar
|
||||||
|
|
||||||
|
actions:
|
||||||
|
- title: Ping host
|
||||||
|
icon: ping
|
||||||
|
shell: ping -c 1 127.0.0.1
|
||||||
|
- title: Restart Docker Container
|
||||||
|
icon: restart
|
||||||
|
shell: echo restart
|
||||||
|
- title: Delete old backups
|
||||||
|
icon: ashtonished
|
||||||
|
shell: echo delete
|
||||||
|
- title: Server ping
|
||||||
|
icon: ping
|
||||||
|
shell: echo ping
|
||||||
|
- title: Container list
|
||||||
|
icon: disk
|
||||||
|
shell: echo list
|
||||||
|
|
||||||
|
dashboards:
|
||||||
|
- title: My Servers
|
||||||
|
contents:
|
||||||
|
- title: Server ping
|
||||||
|
- title: My Containers
|
||||||
|
contents:
|
||||||
|
- title: Container list
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
[DEFAULT]
|
||||||
|
base_url = http://localhost:11337/
|
||||||
|
dir = .
|
||||||
|
width = 980
|
||||||
|
height = 420
|
||||||
|
post_script_sleep = 0.5
|
||||||
|
|
||||||
|
[topbar]
|
||||||
|
url = .
|
||||||
|
name = topbar
|
||||||
|
script = setup_topbar.py
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Capture the topbar section navigation style."""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_topbar_navigation(driver, timeout=30):
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: bool(d.find_element(By.TAG_NAME, "body").get_attribute("loaded-dashboard"))
|
||||||
|
)
|
||||||
|
|
||||||
|
def ready(d):
|
||||||
|
try:
|
||||||
|
topbar = d.find_element(By.CSS_SELECTOR, "nav.topbar")
|
||||||
|
my_servers = d.find_element(
|
||||||
|
By.XPATH,
|
||||||
|
'//nav[contains(@class, "topbar")]//a[contains(normalize-space(), "My Servers")]',
|
||||||
|
)
|
||||||
|
my_containers = d.find_element(
|
||||||
|
By.XPATH,
|
||||||
|
'//nav[contains(@class, "topbar")]//a[contains(normalize-space(), "My Containers")]',
|
||||||
|
)
|
||||||
|
diagnostics = d.find_element(
|
||||||
|
By.XPATH,
|
||||||
|
'//nav[contains(@class, "topbar")]//a[contains(normalize-space(), "Diagnostics")]',
|
||||||
|
)
|
||||||
|
logs = d.find_element(
|
||||||
|
By.XPATH,
|
||||||
|
'//nav[contains(@class, "topbar")]//a[contains(normalize-space(), "Logs")]',
|
||||||
|
)
|
||||||
|
ping_host = d.find_element(By.CSS_SELECTOR, '[title="Ping host"]')
|
||||||
|
restart = d.find_element(By.CSS_SELECTOR, '[title="Restart Docker Container"]')
|
||||||
|
delete_backups = d.find_element(By.CSS_SELECTOR, '[title="Delete old backups"]')
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return topbar.is_displayed() and all(
|
||||||
|
element.is_displayed()
|
||||||
|
for element in (
|
||||||
|
my_servers,
|
||||||
|
my_containers,
|
||||||
|
diagnostics,
|
||||||
|
logs,
|
||||||
|
ping_host,
|
||||||
|
restart,
|
||||||
|
delete_backups,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
WebDriverWait(driver, timeout).until(ready)
|
||||||
|
|
||||||
|
|
||||||
|
def run(driver):
|
||||||
|
_wait_for_topbar_navigation(driver)
|
||||||
|
time.sleep(0.2)
|
||||||
|
After Width: | Height: | Size: 24 KiB |
2
docs/modules/ROOT/images/advanced_configuration/webui/with-navigation/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
custom-webui/
|
||||||
|
__pycache__/
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIGDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
include ../../../screenshots.mk
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
---
|
||||||
|
listenAddressSingleHTTPFrontend: 0.0.0.0:11337
|
||||||
|
|
||||||
|
logLevel: "WARN"
|
||||||
|
checkForUpdates: false
|
||||||
|
showFooter: false
|
||||||
|
|
||||||
|
actions:
|
||||||
|
- title: Ping the Internet
|
||||||
|
icon: ping
|
||||||
|
shell: ping -c 1 127.0.0.1
|
||||||
|
- title: Check disk space
|
||||||
|
icon: disk
|
||||||
|
shell: df -h
|
||||||
|
- title: check dmesg logs
|
||||||
|
icon: logs
|
||||||
|
shell: dmesg | tail -n 1
|
||||||
|
- title: date
|
||||||
|
icon: clock
|
||||||
|
shell: date
|
||||||
|
- title: Run backup script
|
||||||
|
icon: backup
|
||||||
|
shell: echo backup
|
||||||
|
- title: Ping host
|
||||||
|
icon: ping
|
||||||
|
shell: ping -c 1 127.0.0.1
|
||||||
|
- title: Restart Docker Container
|
||||||
|
icon: restart
|
||||||
|
shell: echo restart
|
||||||
|
- title: Delete old backups
|
||||||
|
icon: ashtonished
|
||||||
|
shell: echo delete
|
||||||
|
- title: Get OliveTin Theme
|
||||||
|
icon: theme
|
||||||
|
shell: echo theme
|
||||||
|
- title: Setup easy SSH
|
||||||
|
icon: ssh
|
||||||
|
shell: echo ssh
|
||||||
|
- title: Restart httpd on server1
|
||||||
|
icon: restart
|
||||||
|
shell: echo restart httpd
|
||||||
|
- title: Toggle GPIO light
|
||||||
|
icon: light
|
||||||
|
shell: echo toggle
|
||||||
|
- title: Run Automation Playbook
|
||||||
|
icon: robot
|
||||||
|
shell: echo ansible
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
[DEFAULT]
|
||||||
|
base_url = http://localhost:11337/
|
||||||
|
dir = .
|
||||||
|
width = 1180
|
||||||
|
height = 760
|
||||||
|
post_script_sleep = 0.5
|
||||||
|
|
||||||
|
[with-navigation]
|
||||||
|
url = .
|
||||||
|
name = with-navigation
|
||||||
|
script = setup_with_navigation.py
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Capture the default Actions view with sidebar navigation visible."""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
|
|
||||||
|
def run(driver):
|
||||||
|
WebDriverWait(driver, 15).until(
|
||||||
|
lambda d: bool(d.find_element(By.TAG_NAME, "body").get_attribute("loaded-dashboard"))
|
||||||
|
)
|
||||||
|
WebDriverWait(driver, 15).until(
|
||||||
|
lambda d: len(d.find_elements(By.CSS_SELECTOR, ".action-button button")) >= 8
|
||||||
|
)
|
||||||
|
|
||||||
|
driver.find_element(By.ID, "sidebar-toggler-button").click()
|
||||||
|
|
||||||
|
WebDriverWait(driver, 15).until(
|
||||||
|
lambda d: d.find_element(By.ID, "mainnav").is_displayed()
|
||||||
|
)
|
||||||
|
time.sleep(0.2)
|
||||||
|
After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
|
@ -0,0 +1,2 @@
|
||||||
|
custom-webui/
|
||||||
|
__pycache__/
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIGDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
include ../../screenshots.mk
|
||||||
|
After Width: | Height: | Size: 24 KiB |
|
|
@ -0,0 +1,22 @@
|
||||||
|
---
|
||||||
|
listenAddressSingleHTTPFrontend: 0.0.0.0:11337
|
||||||
|
|
||||||
|
logLevel: "WARN"
|
||||||
|
checkForUpdates: false
|
||||||
|
showFooter: false
|
||||||
|
|
||||||
|
actions:
|
||||||
|
- title: Backup selected directories
|
||||||
|
shell: echo "Backing up {{ directories }}"
|
||||||
|
arguments:
|
||||||
|
- name: directories
|
||||||
|
title: Directories to back up
|
||||||
|
type: checklist
|
||||||
|
choices:
|
||||||
|
- title: Documents
|
||||||
|
value: documents
|
||||||
|
- title: Photos
|
||||||
|
value: photos
|
||||||
|
- title: Music
|
||||||
|
value: music
|
||||||
|
default: '["documents","photos"]'
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
[DEFAULT]
|
||||||
|
base_url = http://localhost:11337/
|
||||||
|
dir = .
|
||||||
|
width = 800
|
||||||
|
height = 520
|
||||||
|
post_script_sleep = 0.5
|
||||||
|
|
||||||
|
[checklist]
|
||||||
|
url = .
|
||||||
|
name = checklist
|
||||||
|
script = setup_checklist.py
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Prepare the checklist argument form screenshot."""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_body_attr(driver, attr, timeout=15):
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: bool(d.find_element(By.TAG_NAME, "body").get_attribute(attr))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def run(driver):
|
||||||
|
_wait_for_body_attr(driver, "loaded-dashboard")
|
||||||
|
|
||||||
|
driver.find_element(
|
||||||
|
By.CSS_SELECTOR, '[title="Backup selected directories"]'
|
||||||
|
).click()
|
||||||
|
|
||||||
|
_wait_for_body_attr(driver, "loaded-argument-form")
|
||||||
|
|
||||||
|
WebDriverWait(driver, 15).until(
|
||||||
|
lambda d: len(
|
||||||
|
d.find_elements(By.CSS_SELECTOR, ".choice-checklist-item input[type='checkbox']")
|
||||||
|
)
|
||||||
|
>= 3
|
||||||
|
)
|
||||||
|
time.sleep(0.2)
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
custom-webui/
|
||||||
|
__pycache__/
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIGDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
include ../../screenshots.mk
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
listenAddressSingleHTTPFrontend: 0.0.0.0:11337
|
||||||
|
|
||||||
|
logLevel: "WARN"
|
||||||
|
checkForUpdates: false
|
||||||
|
showFooter: false
|
||||||
|
|
||||||
|
actions:
|
||||||
|
- title: Delete old backups
|
||||||
|
icon: ashtonished
|
||||||
|
shell: echo "Deleted old backups"
|
||||||
|
arguments:
|
||||||
|
- type: confirmation
|
||||||
|
title: Are you sure?!
|
||||||
|
After Width: | Height: | Size: 16 KiB |
|
|
@ -0,0 +1,11 @@
|
||||||
|
[DEFAULT]
|
||||||
|
base_url = http://localhost:11337/
|
||||||
|
dir = .
|
||||||
|
width = 800
|
||||||
|
height = 420
|
||||||
|
post_script_sleep = 0.5
|
||||||
|
|
||||||
|
[confirmation]
|
||||||
|
url = .
|
||||||
|
name = confirmation
|
||||||
|
script = setup_confirmation.py
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Prepare the confirmation argument screenshot."""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_body_attr(driver, attr, timeout=15):
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: bool(d.find_element(By.TAG_NAME, "body").get_attribute(attr))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def run(driver):
|
||||||
|
_wait_for_body_attr(driver, "loaded-dashboard")
|
||||||
|
|
||||||
|
driver.find_element(By.CSS_SELECTOR, '[title="Delete old backups"]').click()
|
||||||
|
_wait_for_body_attr(driver, "loaded-argument-form")
|
||||||
|
|
||||||
|
WebDriverWait(driver, 15).until(
|
||||||
|
lambda d: not d.find_element(By.CSS_SELECTOR, 'button[name="start"]').is_enabled()
|
||||||
|
)
|
||||||
|
time.sleep(0.2)
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
custom-webui/
|
||||||
|
__pycache__/
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIGDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
include ../../screenshots.mk
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
listenAddressSingleHTTPFrontend: 0.0.0.0:11337
|
||||||
|
|
||||||
|
logLevel: "WARN"
|
||||||
|
checkForUpdates: false
|
||||||
|
showFooter: false
|
||||||
|
|
||||||
|
entities:
|
||||||
|
- file: entities/containers.json
|
||||||
|
name: container
|
||||||
|
|
||||||
|
actions:
|
||||||
|
- title: Print a message
|
||||||
|
icon: smile
|
||||||
|
shell: echo "{{ message }}"
|
||||||
|
arguments:
|
||||||
|
- name: message
|
||||||
|
description: The message you want to print out.
|
||||||
|
choices:
|
||||||
|
- title: Hello
|
||||||
|
value: Hello there!
|
||||||
|
- title: Goodbye
|
||||||
|
value: Aww, goodbye. :-(
|
||||||
|
- title: restart container
|
||||||
|
shell: 'docker restart {{ containerToRestart }}'
|
||||||
|
arguments:
|
||||||
|
- name: containerToRestart
|
||||||
|
entity: container
|
||||||
|
title: Select Container
|
||||||
|
choices:
|
||||||
|
- value: '{{ container.Names }}'
|
||||||
|
title: '{{ container.Names }}'
|
||||||
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
|
@ -0,0 +1,2 @@
|
||||||
|
{"Names":"media-indexer"}
|
||||||
|
{"Names":"game-server"}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
[DEFAULT]
|
||||||
|
base_url = http://localhost:11337/
|
||||||
|
dir = .
|
||||||
|
width = 800
|
||||||
|
height = 480
|
||||||
|
post_script_sleep = 0.5
|
||||||
|
|
||||||
|
[dropdown]
|
||||||
|
url = .
|
||||||
|
name = dropdown
|
||||||
|
script = setup_dropdown.py
|
||||||
|
|
||||||
|
[dropdown-logs-list]
|
||||||
|
url = .
|
||||||
|
name = dropdown-logs-list
|
||||||
|
script = setup_dropdown_logs_list.py
|
||||||
|
width = 960
|
||||||
|
height = 640
|
||||||
|
|
||||||
|
[dropdown-logs-detail]
|
||||||
|
url = .
|
||||||
|
name = dropdown-logs-detail
|
||||||
|
script = setup_dropdown_logs_detail.py
|
||||||
|
height = 560
|
||||||
|
|
||||||
|
[dropdown-entities]
|
||||||
|
url = .
|
||||||
|
name = dropdown-entities
|
||||||
|
script = setup_dropdown_entities.py
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Prepare the dropdown argument form screenshot."""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_body_attr(driver, attr, timeout=15):
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: bool(d.find_element(By.TAG_NAME, "body").get_attribute(attr))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _open_choice_list(driver, input_id):
|
||||||
|
combobox_input = driver.find_element(By.ID, input_id)
|
||||||
|
combobox_input.click()
|
||||||
|
WebDriverWait(driver, 15).until(
|
||||||
|
lambda d: len(
|
||||||
|
d.find_elements(
|
||||||
|
By.CSS_SELECTOR,
|
||||||
|
f"#{input_id}-listbox li, #{input_id} + input + ul li",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
>= 2
|
||||||
|
or len(d.find_elements(By.CSS_SELECTOR, ".choice-combobox-list li")) >= 2
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def run(driver):
|
||||||
|
_wait_for_body_attr(driver, "loaded-dashboard")
|
||||||
|
|
||||||
|
driver.find_element(By.CSS_SELECTOR, '[title="Print a message"]').click()
|
||||||
|
_wait_for_body_attr(driver, "loaded-argument-form")
|
||||||
|
_open_choice_list(driver, "message")
|
||||||
|
time.sleep(0.2)
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Prepare the entity-backed dropdown screenshot."""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_body_attr(driver, attr, timeout=15):
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: bool(d.find_element(By.TAG_NAME, "body").get_attribute(attr))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _open_choice_list(driver, input_id):
|
||||||
|
combobox_input = driver.find_element(By.ID, input_id)
|
||||||
|
combobox_input.click()
|
||||||
|
WebDriverWait(driver, 15).until(
|
||||||
|
lambda d: len(d.find_elements(By.CSS_SELECTOR, ".choice-combobox-list li")) >= 2
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def run(driver):
|
||||||
|
_wait_for_body_attr(driver, "loaded-dashboard")
|
||||||
|
|
||||||
|
driver.find_element(By.CSS_SELECTOR, '[title="restart container"]').click()
|
||||||
|
_wait_for_body_attr(driver, "loaded-argument-form")
|
||||||
|
_open_choice_list(driver, "containerToRestart")
|
||||||
|
time.sleep(0.2)
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Prepare the execution results screenshot for a dropdown action."""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_dashboard(driver, timeout=15):
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: bool(d.find_element(By.TAG_NAME, "body").get_attribute("loaded-dashboard"))
|
||||||
|
)
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: d.execute_script("return !!window.client")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_logs_page(driver, timeout=15):
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: "/logs/" in d.current_url and not d.current_url.rstrip("/").endswith("/logs")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_execution_complete(driver, timeout=15):
|
||||||
|
def finished(d):
|
||||||
|
try:
|
||||||
|
status = d.find_element(By.CSS_SELECTOR, ".execution-dialog-status").text
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
return "Still running" not in status and "Queued" not in status
|
||||||
|
|
||||||
|
WebDriverWait(driver, timeout).until(finished)
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_terminal_output(driver, expected, timeout=15):
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: expected
|
||||||
|
in d.execute_script(
|
||||||
|
"""
|
||||||
|
if (!window.terminal || !window.terminal.getBufferAsString) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return window.terminal.getBufferAsString();
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def run(driver):
|
||||||
|
_wait_for_dashboard(driver)
|
||||||
|
|
||||||
|
driver.execute_async_script(
|
||||||
|
"""
|
||||||
|
const done = arguments[arguments.length - 1];
|
||||||
|
const button = document.querySelector('[title="Print a message"]');
|
||||||
|
const bindingId = button.closest('.action-button').id.replace('actionButton-', '');
|
||||||
|
|
||||||
|
window.client.startAction({
|
||||||
|
bindingId: bindingId,
|
||||||
|
arguments: [{ name: 'message', value: 'Hello there!' }],
|
||||||
|
uniqueTrackingId: 'doc-screenshot-' + Date.now(),
|
||||||
|
}).then((response) => {
|
||||||
|
window.location.href = '/logs/' + response.executionTrackingId;
|
||||||
|
done(true);
|
||||||
|
}).catch((err) => done(String(err)));
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
_wait_for_logs_page(driver)
|
||||||
|
_wait_for_execution_complete(driver)
|
||||||
|
_wait_for_terminal_output(driver, "Hello there!")
|
||||||
|
time.sleep(0.2)
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Prepare the logs list screenshot after running a dropdown action."""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_dashboard(driver, timeout=15):
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: bool(d.find_element(By.TAG_NAME, "body").get_attribute("loaded-dashboard"))
|
||||||
|
)
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: d.execute_script("return !!window.client")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_logs_table(driver, timeout=15):
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: len(d.find_elements(By.CSS_SELECTOR, ".logs-table tbody tr")) >= 1
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def run(driver):
|
||||||
|
_wait_for_dashboard(driver)
|
||||||
|
|
||||||
|
driver.execute_async_script(
|
||||||
|
"""
|
||||||
|
const done = arguments[arguments.length - 1];
|
||||||
|
const button = document.querySelector('[title="Print a message"]');
|
||||||
|
const bindingId = button.closest('.action-button').id.replace('actionButton-', '');
|
||||||
|
|
||||||
|
window.client.startAction({
|
||||||
|
bindingId: bindingId,
|
||||||
|
arguments: [{ name: 'message', value: 'Hello there!' }],
|
||||||
|
uniqueTrackingId: 'doc-screenshot-' + Date.now(),
|
||||||
|
}).then(() => done(true)).catch((err) => done(String(err)));
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
time.sleep(0.5)
|
||||||
|
driver.execute_script("window.location.href = '/logs'")
|
||||||
|
_wait_for_logs_table(driver)
|
||||||
|
time.sleep(0.2)
|
||||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 26 KiB |
|
|
@ -19,3 +19,4 @@ script = setup_args2.py
|
||||||
url = .
|
url = .
|
||||||
name = args3
|
name = args3
|
||||||
script = setup_args3.py
|
script = setup_args3.py
|
||||||
|
height = 560
|
||||||
|
|
|
||||||
|
|
@ -65,5 +65,15 @@ def run(driver):
|
||||||
|
|
||||||
_wait_for_logs_page(driver)
|
_wait_for_logs_page(driver)
|
||||||
_wait_for_execution_complete(driver)
|
_wait_for_execution_complete(driver)
|
||||||
|
WebDriverWait(driver, 15).until(
|
||||||
|
lambda d: "Hello World"
|
||||||
|
in d.execute_script(
|
||||||
|
"""
|
||||||
|
if (!window.terminal || !window.terminal.getBufferAsString) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return window.terminal.getBufferAsString();
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
)
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
custom-webui/
|
||||||
|
__pycache__/
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIGDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
include ../../screenshots.mk
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
---
|
||||||
|
listenAddressSingleHTTPFrontend: 0.0.0.0:11337
|
||||||
|
|
||||||
|
logLevel: "WARN"
|
||||||
|
checkForUpdates: false
|
||||||
|
showFooter: false
|
||||||
|
|
||||||
|
actions:
|
||||||
|
- title: Save text to file
|
||||||
|
shell: 'echo "{{ content }}" > file'
|
||||||
|
arguments:
|
||||||
|
- type: raw_string_multiline
|
||||||
|
name: content
|
||||||
|
title: Content
|
||||||
|
default: |
|
||||||
|
Line one of the message
|
||||||
|
Line two of the message
|
||||||
|
After Width: | Height: | Size: 18 KiB |
|
|
@ -0,0 +1,11 @@
|
||||||
|
[DEFAULT]
|
||||||
|
base_url = http://localhost:11337/
|
||||||
|
dir = .
|
||||||
|
width = 800
|
||||||
|
height = 520
|
||||||
|
post_script_sleep = 0.5
|
||||||
|
|
||||||
|
[multiline-text]
|
||||||
|
url = .
|
||||||
|
name = multiline-text
|
||||||
|
script = setup_textarea.py
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Prepare the multiline textarea argument screenshot."""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_body_attr(driver, attr, timeout=15):
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: bool(d.find_element(By.TAG_NAME, "body").get_attribute(attr))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def run(driver):
|
||||||
|
_wait_for_body_attr(driver, "loaded-dashboard")
|
||||||
|
|
||||||
|
driver.find_element(By.CSS_SELECTOR, '[title="Save text to file"]').click()
|
||||||
|
|
||||||
|
WebDriverWait(driver, 15).until(
|
||||||
|
lambda d: len(
|
||||||
|
d.find_elements(By.CSS_SELECTOR, "#argument-popup textarea#content")
|
||||||
|
)
|
||||||
|
>= 1
|
||||||
|
)
|
||||||
|
time.sleep(0.2)
|
||||||
|
Before Width: | Height: | Size: 17 KiB |
|
|
@ -0,0 +1,2 @@
|
||||||
|
custom-webui/
|
||||||
|
__pycache__/
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIGDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
include ../../screenshots.mk
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
listenAddressSingleHTTPFrontend: 0.0.0.0:11337
|
||||||
|
|
||||||
|
logLevel: "WARN"
|
||||||
|
checkForUpdates: false
|
||||||
|
showFooter: false
|
||||||
|
|
||||||
|
actions:
|
||||||
|
- title: Placeholder 1
|
||||||
|
shell: echo "placeholder 1"
|
||||||
|
- title: Placeholder 2
|
||||||
|
shell: echo "placeholder 2"
|
||||||
|
|
||||||
|
dashboards:
|
||||||
|
- title: My First Dashboard
|
||||||
|
contents:
|
||||||
|
- title: Fieldset 1
|
||||||
|
type: fieldset
|
||||||
|
contents:
|
||||||
|
- title: Folder 1
|
||||||
|
contents:
|
||||||
|
- title: Placeholder 1
|
||||||
|
- title: Folder 2
|
||||||
|
contents:
|
||||||
|
- title: Placeholder 2
|
||||||
|
After Width: | Height: | Size: 9.4 KiB |
|
|
@ -0,0 +1,11 @@
|
||||||
|
[DEFAULT]
|
||||||
|
base_url = http://localhost:11337/
|
||||||
|
dir = .
|
||||||
|
width = 980
|
||||||
|
height = 400
|
||||||
|
post_script_sleep = 0.5
|
||||||
|
|
||||||
|
[fieldset]
|
||||||
|
url = /dashboards/My%%20First%%20Dashboard
|
||||||
|
name = fieldset
|
||||||
|
script = setup_fieldset.py
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Open My First Dashboard from dashboards/2-fieldsets.adoc."""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_fieldset_dashboard(driver, timeout=30):
|
||||||
|
WebDriverWait(driver, timeout).until(
|
||||||
|
lambda d: d.find_element(By.TAG_NAME, "body").get_attribute("loaded-dashboard")
|
||||||
|
== "My First Dashboard"
|
||||||
|
)
|
||||||
|
|
||||||
|
def ready(d):
|
||||||
|
try:
|
||||||
|
folder1 = d.find_element(
|
||||||
|
By.XPATH,
|
||||||
|
'//button[contains(@class, "directory-button")]//span[contains(@class, "title") and text()="Folder 1"]',
|
||||||
|
)
|
||||||
|
folder2 = d.find_element(
|
||||||
|
By.XPATH,
|
||||||
|
'//button[contains(@class, "directory-button")]//span[contains(@class, "title") and text()="Folder 2"]',
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
return all(element.is_displayed() for element in (folder1, folder2))
|
||||||
|
|
||||||
|
WebDriverWait(driver, timeout).until(ready)
|
||||||
|
|
||||||
|
|
||||||
|
def run(driver):
|
||||||
|
_wait_for_fieldset_dashboard(driver)
|
||||||
|
time.sleep(0.2)
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
custom-webui/
|
||||||
|
__pycache__/
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIGDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
include ../../screenshots.mk
|
||||||