Initial Commit
This commit is contained in:
commit
343a7f7dd6
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.venv/
|
||||
11
data/screen_settings.json
Normal file
11
data/screen_settings.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"url": "yahoo.com",
|
||||
"mediaFolder": "playlist",
|
||||
"imageDuration": "5",
|
||||
"player_type": "mpv",
|
||||
"mediaLocation": "/home/orangepi/Desktop/playlists/ATA",
|
||||
"autoStart": true,
|
||||
"autoStartDelay": 5,
|
||||
"autoPlayAtBoot": true,
|
||||
"browserPath": "chromium"
|
||||
}
|
||||
2
dist/pyarmor_runtime_000000/__init__.py
vendored
Normal file
2
dist/pyarmor_runtime_000000/__init__.py
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# Pyarmor 8.5.10 (trial), 000000, 2025-01-12T20:49:57.897614
|
||||
from .pyarmor_runtime import __pyarmor__
|
||||
BIN
dist/pyarmor_runtime_000000/pyarmor_runtime.so
vendored
Normal file
BIN
dist/pyarmor_runtime_000000/pyarmor_runtime.so
vendored
Normal file
Binary file not shown.
38
requirements.txt
Normal file
38
requirements.txt
Normal file
@ -0,0 +1,38 @@
|
||||
beautifulsoup4
|
||||
blinker
|
||||
bs4
|
||||
certifi
|
||||
cffi
|
||||
charset-normalizer
|
||||
click
|
||||
cryptography
|
||||
decorator
|
||||
dogpile.cache
|
||||
flask
|
||||
Flask-Cors
|
||||
gunicorn
|
||||
idna
|
||||
importlib-metadata
|
||||
itsdangerous
|
||||
jinja2
|
||||
MarkupSafe
|
||||
packaging
|
||||
pbkdf2
|
||||
pbr
|
||||
psutil
|
||||
pyarmor
|
||||
pyarmor.cli.core
|
||||
pycparser
|
||||
pycups
|
||||
python-vlc
|
||||
pyudev
|
||||
requests
|
||||
soupsieve
|
||||
spidev
|
||||
stevedore
|
||||
swig
|
||||
typing-extensions
|
||||
urllib3
|
||||
werkzeug
|
||||
zipp
|
||||
|
||||
3
src/MPVPlayer.py
Normal file
3
src/MPVPlayer.py
Normal file
File diff suppressed because one or more lines are too long
3
src/MPVPlayer_orig.py
Normal file
3
src/MPVPlayer_orig.py
Normal file
File diff suppressed because one or more lines are too long
3
src/VideoPlayer.py
Normal file
3
src/VideoPlayer.py
Normal file
File diff suppressed because one or more lines are too long
BIN
src/__pycache__/VideoPlayer.cpython-310.pyc
Normal file
BIN
src/__pycache__/VideoPlayer.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/VideoPlayer.cpython-311.pyc
Normal file
BIN
src/__pycache__/VideoPlayer.cpython-311.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/app.cpython-310.pyc
Normal file
BIN
src/__pycache__/app.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/app.cpython-311.pyc
Normal file
BIN
src/__pycache__/app.cpython-311.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/find_usb_folder.cpython-310.pyc
Normal file
BIN
src/__pycache__/find_usb_folder.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/find_usb_folder.cpython-311.pyc
Normal file
BIN
src/__pycache__/find_usb_folder.cpython-311.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/get_playlists.cpython-310.pyc
Normal file
BIN
src/__pycache__/get_playlists.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/get_playlists.cpython-311.pyc
Normal file
BIN
src/__pycache__/get_playlists.cpython-311.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/globals.cpython-310.pyc
Normal file
BIN
src/__pycache__/globals.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/globals.cpython-311.pyc
Normal file
BIN
src/__pycache__/globals.cpython-311.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/play_usb_media.cpython-310.pyc
Normal file
BIN
src/__pycache__/play_usb_media.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/play_usb_media.cpython-311.pyc
Normal file
BIN
src/__pycache__/play_usb_media.cpython-311.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/resources.cpython-310.pyc
Normal file
BIN
src/__pycache__/resources.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/resources.cpython-311.pyc
Normal file
BIN
src/__pycache__/resources.cpython-311.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/wifi_config.cpython-310.pyc
Normal file
BIN
src/__pycache__/wifi_config.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/wifi_config.cpython-311.pyc
Normal file
BIN
src/__pycache__/wifi_config.cpython-311.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/wsgi.cpython-310.pyc
Normal file
BIN
src/__pycache__/wsgi.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/wsgi.cpython-311.pyc
Normal file
BIN
src/__pycache__/wsgi.cpython-311.pyc
Normal file
Binary file not shown.
3
src/app.py
Normal file
3
src/app.py
Normal file
File diff suppressed because one or more lines are too long
3
src/find_usb_folder.py
Normal file
3
src/find_usb_folder.py
Normal file
File diff suppressed because one or more lines are too long
3
src/get_display.py
Normal file
3
src/get_display.py
Normal file
@ -0,0 +1,3 @@
|
||||
# Pyarmor 9.0.7 (trial), 000000, non-profits, 2025-03-05T12:22:13.847182
|
||||
from pyarmor_runtime_000000 import __pyarmor__
|
||||
__pyarmor__(__name__, __file__, b'PY000000\x00\x03\n\x00o\r\r\n\x80\x00\x01\x00\x08\x00\x00\x00\x04\x00\x00\x00@\x00\x00\x00e\x03\x00\x00\x12\t\x04\x00:\x81\xd6u\x83\xf4\xacR\xbbSmm\x9d\xa9\xf2\x8c\x00\x00\x00\x00\x00\x00\x00\x00\x85\xb7 \xad\x80\xbb\x7f\x90\x1f\n\x9f7\xe4\xc2R\xae&s\x0c\x11\x97\x12\xa4\x1f\xd53\r\xbbU]\x82t\xfa\t\xd4\xbf\xd2oTl\xfe\xf7\x92\xea\x9c4\x94\x13b\xc9\xc9\xe6+,\x98\x81\xa3\xc8w\xb5"\xd3\x0e6j\x00\x01\x01\xcb\xce\xa3\x1bC\xcf\xb5\xec\x06|(a\xe5\xaf}.\xb1\xef\xfbC\xe7\xce\xcaqFA\xf5\xf7\x1d:\x13\x0b<\x86\r\x0cx\xb8))"\xbb!\xef\x18\xd9l\xe0\xf27\x97\xec\x8a}P>\xdd\xd1(\xd1>c\xaf\x96,C\x04\xacQ\xecZ\xf3x\xaf\xc3\xa1\xcf`\xb7y\xba\xad\xe0\x10\xb3Ni\x1e\xa9\xe2.\xfa5\xe5Nnl|c@\x9c\x8a\x95\x189\xc9\xcfbP\xca\xb0\xbf\xedr-rO$\xab\x05qH\xb2\x01\r\xeaC*f><\xfb\xa0E<Vd\x98\x8bt\xae\x1bU\xfepF\xf3H\xbe)\x94\xe6sM\xde8\xc9\xd7\xa6 \x06\x12D[9\xd8\xed\x0f\xa48\xc0\xa4\x80]$\xd8\x1c\x1a\xee\xde\\\xab\x1b\xd6\xb5\x8c,?\xae\x8f\xf4%\x7fh\xef.\x1c\xd1\xdc\xf2\x03"\xa0\xf4A\x00\xe0\xb5\xff\xfb8\xa1\xfe\xabN\t\xb0v\\/X\xff\xd3\n\xf6\t\'F\xa6M\xb5\xdb\xba\xc3\x00\xecO\xe0O\x8a\x04P8U\xb1\x8f\x14\xf4\xe3\x05\x0eP\xff\xae\xfc\xda\x1d\x1a\xa7?Y-\x8c1Z\xb6\xd9CX[\xef\x03\x0f\x86\xe1\xb69oz\x01\x05{{\xdcz,qt;\x88\xceL\xe3\xaa\xe8}\x83\x0f\xb6#\xf7\xfc8\xcc\xee\xc3\xd3\xed\x0f\x14\xe3\xf8\x8a\x95F*:\xa0)LG\x07\x13\x12\xef7qk\':\xd4Y\xe1\xd8\x8d`*\xf4\tvDeo\x10<\x8a\x94\xc6/\xd6\xd2P\xd6\xb4~\xd4N\xca\x1d\xb5\xf3\xae\xaa\x9a\xc5c\x15\xba\x97%G\x96\xf8g\xbaYv\xb0m\xe16\\\x80\xb5\x1a\xa1(B+\xdfq\xc6\xa9\xdc>gh\xce\xe3c\xe6t\xec\xed\x89\x82c\x12;(\tF\x15\xc1\x9e\xeer\x10\xde\x99\xe2\xe8\xaeS\x81\xb0\xa0\xb8\xd2\xbc\xf0v\xe5T\xe8\xc8\x00\x88|\x82\xb8\x03\xa2\x92\xd3\xd0\xdd#\xf5\xd5T\xcc\xd9\xe3%\xec\x83ZN\x98\xeer\xcc\x19<|\xbdh\xf1*:)j\xe9;/\'[\xe5\xcaA\x94p\xf2\xfd\xbb\xbe^RC\xc8\x9a\xb9\xf21\x06\xbd&\xe8u\x94\x19!\xdat6\xe9\x0f\x8c\xfc\x15\x06."\xe0\x1e\xeb\x1e\xf5\xbb\r\x01W\x83\x92sm\xb3m\xc8\xe9e\x01O\xba\xfa1oy-Lo\xd3R$I\xc4\x83\r\'t\xf1\xfc\x12\xda\\\n\xb1\xc67\xa3wq=\xa9\xda\x80\x06\xb2\x87\xbd\x90T\xc2\xf5m5\xd2qP\x00\x88u\xba\x8d\x7f\x8d\x95\x8f\x9e\x90\x879^\xd7\xe2)\xe3\x94X\xa1\xa4\x1a\x01\xe3\xc8\rB\xccI:\x93\x9fZ\xc2\xb4\xb4\x0b\xaa\xd5\xc7\x05\tf\xf5c\xb8&`\xd0\xa8\xa3\x82\x0coe]\x056\x8cu\x87\xd3\x82\t\x80\x846\xc7\xbb\xaf#\xcaam5w\x03`\x91n\'\xc8:\x94\x13\x89\xd9\x98s\x15]9\x90\xf1\xdd\xa9,\x98\xa3\x1f\xcf0_cK\x86\x84#\xb0\r\x19\xf9Z\xd0\xe3\x1c\x83.\xa1\xd9%e<^M\xa7/\x14\xf7\x89O\x89D\xa2*\xdd2\xd0\xcc\xad\x0f\xfa\xd2\x8c\x83\xb3\x94\xcb|p\xb2\xdb\xa3)\x9a\x8d\x03H\x07\xa3\x15\xfc\n<\\\x1d\xeb\x07\xfb\xbe\xd3\xbbc?qm\xee\x08\x89\xb5\x19|J\xab\xe7g}R\x11\xbb\xb4l\x93\xa3\x0f\xd2]\xa2>\xe3U\xcdh\xb0\x8e\xd3\xf5YS/Y\xc1/\xfa\xd8\xb8\xc5BP\xa4')
|
||||
3
src/get_playlists.py
Normal file
3
src/get_playlists.py
Normal file
File diff suppressed because one or more lines are too long
3
src/globals.py
Normal file
3
src/globals.py
Normal file
File diff suppressed because one or more lines are too long
3
src/license_checker.py
Normal file
3
src/license_checker.py
Normal file
File diff suppressed because one or more lines are too long
BIN
src/mpv-shot0001.jpg
Normal file
BIN
src/mpv-shot0001.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 331 KiB |
3
src/play_usb_media.py
Normal file
3
src/play_usb_media.py
Normal file
File diff suppressed because one or more lines are too long
2
src/pyarmor_runtime_000000/__init__.py
Normal file
2
src/pyarmor_runtime_000000/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
# Pyarmor 9.0.7 (trial), 000000, 2025-03-05T12:22:13.488747
|
||||
from .pyarmor_runtime import __pyarmor__
|
||||
BIN
src/pyarmor_runtime_000000/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
src/pyarmor_runtime_000000/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/pyarmor_runtime_000000/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
src/pyarmor_runtime_000000/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
src/pyarmor_runtime_000000/pyarmor_runtime.so
Executable file
BIN
src/pyarmor_runtime_000000/pyarmor_runtime.so
Executable file
Binary file not shown.
3
src/resources.py
Normal file
3
src/resources.py
Normal file
@ -0,0 +1,3 @@
|
||||
# Pyarmor 9.0.7 (trial), 000000, non-profits, 2025-03-05T12:22:14.160307
|
||||
from pyarmor_runtime_000000 import __pyarmor__
|
||||
__pyarmor__(__name__, __file__, b'PY000000\x00\x03\n\x00o\r\r\n\x80\x00\x01\x00\x08\x00\x00\x00\x04\x00\x00\x00@\x00\x00\x00\x0b\x03\x00\x00\x12\t\x04\x00\xa5\xad=\xdfl\x98\xc7s{G\x13\xa1\xc0i\r\xc9\x00\x00\x00\x00\x00\x00\x00\x00\xff\x8en<\x1c\x85K@\r\xfd\x04\xdbX\xb1f\x03\x17\x89\xb6\xf7\xf5}2\xfd[\x1b\x08\xd6s\x8a\xb4\xbd\xdaU\x94\x8e\xbb-<@b\x9a+\xdf\xac\xc7\xc1\x92\x1e\x8f\xf1At\xf6\xc7bh\'ly*\x9f\x94?MXOb\xf4\xa8\xc7\x07\xcdx$+U\xdf<a<\nN\xdb\xd6M\x03\xd8\xe2\x007h1\xb4\x8e\xe9\x8b^\x80XA\xd9\xd5\x97*\x860\x19\x97]\x1bI\xc2$95\x90\xe3\x91\xb6\xb6_\xc6\x80>8\xad\r\xe1\x83\x15)\x87\x9eq\xcfN\xc2GL\x83\x01d\xa1v6\x1a\xfe\xc6\xe7\x86\xc2\tZ,\xfa\xc6iv\x90\xcd1&\x1d\xb8\x18\x8b\x7fW!\x9a%\xf4;#\x12\xdd\xa9\x1c(w\xca\xb6\xc7\x85\xee60\xefI\x93\xd0x.$\\\x80n1\x9en\xde\x1e\xd6\xfc\x07\xed\x1b?\xa9\xc5F\xa9\nR\x16\xb1.\xa4\x87\xb67#\xd5;\x8a\xdbH\x02W\xf2\x83\x8eK\x1b\x8bP_\xdby\x82\xdc\x83\x13\x86w\xcf\x9di\x93\xbe`S\x96\x8bP\x93}X\xe7C\x02\xed1\x07b=<\xe7\xf9.\x96\x9c7\xa8\xb3\xc2\x0f\xe5mA\x87q\xbb\xb5\x16;\xe0\xf3\x13\xc3\x05\xd8\xbd\xd9\x07}\x17\x7fk\x82\x91\xe3\xfb- \\m\x05\x8d\xb5)\x0f\xa6\x00G\xb2\xa0\xc1\xca\xc1\xd0\x8bu\x87\xbf\x18K\xd9T\x8cs\te\xd4s`\xb2VG\xdc!\xb4\xed\x7f\xcc]N\x9f|{\xe8W\xfb@V%p=\x93,\xa4\xa9\xd3\\\xfc\xe7\x9e\xfbAG\x08\xb3\x0f\xd8\xf4\x8c\xb6\x80~\xaa\xd2\xf8)\n\x19\xaa?\x0eD\xd1\xb3\xf1\tJ\xf6\xa1 ^\x05\xcbbk\xea\x08\xa3\xb1T\x0f\xcb\xc7\x82\xcbD\xc7\x94<\x93\x17\x9a\x8f#\x16\xe6\xc6\r\x05i\x19\x8a\x08\xb5r\xf2 \xa1\x1f)\xd0\x81\xc3\xd339o\xeaY\x036?\xd5\x1c\x98W\xf1A\xd4\xfd\xba\xd5\x9a\x10\xfe\xd4 \x03\xe4\xd0F\xf3\x984\xb2F\xad1]\xb3}a\xd6\xa8{"\x16\xdan`\x0f\x8e\x81\'\xf6\x88\x9f_\x02\xce\xff\xd3\x12\x05\x17[9I\x11:W\x1f\x1a\xd2\xa8\x02\x97\x9cQ6\x9dP)\x1f\x8f\xa6P_pg\x98d\x84\x85&5\xc6b\xd6\xf9s\xcb\xd1x\x16\xb2[\xa7\xa8E\x8ed\xbasc;|h\x88\xa6\xae:\x0e\xb8\xf5\xbb \x01<{:\x04D/|t\xc9^\xfe\xb0\x1a\xc6\x85\x91\n<\x13[\xf0I\xe2\xc0\xfa\xa7\x7f\xc0\xc9U\xd1\xc1\xeb\xba\xc6d{\x07\xa9o\xc6\xac\x84\xdf,V\xd8\r\xa3\xbf\x1e\x9f\x93\xb7}b\xcd\x16\x85\xd5\x9b%\x86\x87\xaf\xd0\x83\xc4\xc7\xb6_aR\xa7-\xa5\xfd2e\xd3\xcb\xa7\xcd\xb2\xf8i\x8b\x03\x87\xa3\xa3\xbf\xea\x18\x95;\xd1W\xe0\xa4F\xf4\xa5(\xc5B]\x0b\xacP\x8d\x11\x9c\xb7\'\xa3X\x99\xa6\x9c\x88\xc7\x89V1O\xc7;wie\xc3\xc4\x82}l\xe5\x109\x8d\xcc\xb8\xda \xfc`\xec\x17*B\xbaR\xb8T8Y!\x86\xd8W":-&\xcc\xbd\x8b\xc3\xc9\x10M\xda,\x05\xc6"\xcaBK\xf4k{\xa64D\xc1\xda\x11\xe7\'\xbaF=e\xafB\xf0\xa4A\x8b0B\xf0F\x81$A\xd7N]\xbe\xc0\xa2')
|
||||
3
src/spi_flash.py
Normal file
3
src/spi_flash.py
Normal file
File diff suppressed because one or more lines are too long
3
src/t_test.py
Normal file
3
src/t_test.py
Normal file
@ -0,0 +1,3 @@
|
||||
# Pyarmor 8.5.10 (trial), 000000, non-profits, 2025-02-02T07:28:54.847953
|
||||
from pyarmor_runtime_000000 import __pyarmor__
|
||||
__pyarmor__(__name__, __file__, b'PY000000\x00\x03\n\x00o\r\r\n\x80\x00\x01\x00\x08\x00\x00\x00\x04\x00\x00\x00@\x00\x00\x00\xed\x05\x00\x00\x12\t\x04\x00g\xc0\x883\xe7\x9e\xe8S\xdc0\x90\xe9K\xb3S\xe1\x00\x00\x00\x00\x00\x00\x00\x009\xa70\xcc\xf95\x12*O\x87\xea}\xf3\x9b\xf1\xedm\x0f\xf3\xd9T\xe1\xff\xf5P\x1bX\xf6b\x91\xe6ej\xb8_\x1c`&Y4/\xd6\x84h>>|\xa5F\x9fu7\x8b7T\x17J+A\xe6\x11\xf3\xdcg\xf7\x7f\xf7\xb3\xa7,O\x95\xa6\xc3\xb4 \x97x\x17]\xd3\xe8\xb9\x87dPr+\x06\\\xedbg\x0fa\xa0\xe0w5C\x9f\xd0\xf0\x91\xa3_\xcf\xee\xbb`\xa7x\xff\xdat\xf9\xa8"\xde\x98\xe2\xac\xc9\x0c+\x1f_\x12G\xfbL\x9b\xa5C\r\x86\'7\x08r\xe0\x07\xf8\x0e3*e\xc6%\xd6U\xd6\xfd\xd1\xac\xfd\xads\xda\xd0,\x81h1-\xf7\xc1w\xb8\x87\'\x04\x88\xddX%\x1c\xc3Q\xc2\x1b=F\x83\x91\xb9\x0f~\x93\xa7\x8fo\x84G6k\x92zJ\x12\xd0\xf0\x9b-\xc9\xf85[3\xa4#\xbd\xc5\x18|\xda\x84\xca\x9f\xa9\x03\x11\x00\xd7\xa7"\xed\x83X\xda\xec>\x89\x12\xae5\xd5\x08A\xcf\x82\xb88|h6[/\x9bS)\xc7C\x97\xd7h\x1e\xbc\xbdM:03\x83\x9d~U\xad\x1b\x9a\xfa\xac\xae\tO|-\x98\xd7S\x92+MP|\x92\xa9\xca\xea\xc5\x14\xcb/Lk=\x03^|m\xa2\x01\x9d.A\xcd\x91\xeb\x059\xcf\x1b5G\xe7"\xc0\xbf\xd1\xc3L\xd9\xbb\xd6\x88\xcd57%\xed\xbd,n=g\xe17\x04\x1b\xb7\xee\xbc\xdc\x98\xf2&\x15\xaa{\xa6\xec\x9a\xe4\x11Q\x95[\x9b\xd3\x03\xef\xfd\xe8\r\xc6b:EK\x12\x8aiar}\x7f\xe6\xc3}%\xb1J\x9a\x01\xd5\x93\xbe~P\xf5P\xd6\xf0^\x08\xc1\xd7B\x8d*\xa8\xa5\x0cJ\x92\xcc#\x00J\x85x\xbe\xe25\xabbm\x02\xa8\x04|m\xcb\xc4(\x06\xca\x947\xb1\xe9*\x06\xca\xa0X\xd7\xd4\x91\xafW\x95\xdb*\x1b\\\x08\xaf<\xae\xf57d`\x92\xdffe\x9b\xc4\xf6i\x94%C\x99\x16\xec_\x95\xd6w\xaex8\\\xc9\x07\xe4\x81\xa4\xa3\xed\xc7\xed\xfd\xe0\xfb<\x1c\x96\x87\xdbK6d\xe4\xa9\x99\x17\x1fhmN\xa4U\xd3ct\t\xfb~\xd0Q\x0f\xf7&\xe5p=\x1b\xa7\x11\x08\xad\xcc\xd0\xa33\xc8\xf7\xa6K\xecZy\xee\xc9\xca\xbeTU\xee8\x85\x8f\xf7*\xb45\xb5\x0e,\x06\x1dG46\xa9\xae?\x9c\x7f$\xa7A\x17k\x81s\xdd\x85\x99\xfa\x84Q+$\x0eR\x162\x0c\xc6\x15\xf4\x82vQ\xf1"\xf2\x904\xef\x13t\x17dwTw\x00\xf7\t\x9a\xb5\xec\t\xf0\x9c\xb8\xd5a\xb0\xdc\x97]\xd4\xaf\x0cY\xa7\xca\x82\x03\xcb\xb1\xec\x8b\xb5Y\xba\xb1j\x91S\x04\x8e\xf6\xacQ\xf5\xf0\x94)\xdc0\xc4XG7\xf7\xd3=\x9b\xd8\xc8\x989\xb2\x89O\xc98\xcf-,"\x8f\x06\xad\xd9\xdf\x98\x8a\xac\x84iN\xc9X\xb3y\x8b\xe6%t^\xd6\x93\x19\xbc\x04\xa6\xfd3Q\xb5\xb1Q\xbd6\x0f\xc9x\xeeH\x14\xed\xe8FRFd\xb1\x03\x9c4Q\x9d\x9cU\xf4h\x85j\x04M\xd6\x9d\xc7~\xec\x8d\x82O\xba\x1b\xcc\x14>\x87<*\xcf\x99\x1f\x07A*T\x06\x85f%Q{\xbb!5G\xf2\x82\xb8\xbb7%V\x9ev\x08\xb4|\xd0\xe7b\xfc\x1f\xb6C5\xa1\x80\xc9\x1c\xe4\x9c\xee\xe6\x95\xf0\x8ay\x80\xaaR1\x97\xe2\x0f$\xcb\x99\x91\xe7\xb4>\xb9\xbfu\xcd\xbe\xaci\x016hT\xfc\x9a\x0bA\x0e3\x7f\xca\xc8\x0e\x087\xd1\x82\x14\x99\xd5\x92.5\xd4\x84\x90\xbf\xc4\xd3\xca\x1a\x98\x12\x03\x12fq\xa9(\x92|\xad\x80\tW^\xbd\x9cV\xccx\n\xd1\xf9\xbd\xcd\xa1*\x95\n\\\x16\xfb\xe7\xc7\xe8z\x85\x15\x1e\xbe\xf9\xfa:\xe5e\xd3\xf8\x00\xbc$\x91\xe4\xa4\xb8\n\xb9v\xa9c\x9dr@\r\xcf3U\xae\x05\xdf\xa5}4\x90\xf8QO\xca\xf5\xe2\x8aC\x16\x7f\x96\xb2\x1b\xfe\xfb\xedBs\xe9h\'\xe2\xaaY\x00G\\\x0c\xf0u\x8c\xc5\x95\xdf\xb817\xa4\x88\x1e\xc2o\x8c\xe5\xde\xfe(\xb4#\xc7\xf9\xd3\xe3\xfbQ\x9e\xb3r|\x7f\xad\xaf\x1bd\'\x93\x04\xc0\x07\xd0(c\xf32Q\xc5\x9a\x19\x19\x9ccK\xc9\r\xd1\x94\xf7\x98\xc8\xb8\xf2\x84\xd6\x8f\xec\xdb\xab\x88\x83\xbdT\xebWEB\xb7M\x7f\xa0\x7f\xc5\xb3\xa1S\xa1*Po\xc9{}\x81\xab\xe2BI\xd3\xa9\x91\x8b`\xa9\xf4\x84$\xb0\x1d\xe2\xc3\x90jQ\x93j`^\xf5\xacd\xdeTM.\xe0\xf2\xday\x0e)+\n\x16\x8e\r\x08\xaa\xed*1\xc8p^\x1e\xbc\xabP \xd1\x80\xe8\xe3Ws\xe7\x91\x8f\x8b\x8e\xba\xbf\n\xc1\xb3\xaa\xdc\xdc\xe7\xbc\xed\x11\xa2\xf9\xe7\r\x1c)\xd9\xa8\xe8\x85ON\xf2!6\xdf\xacj\x08\x8c\xda\xe1_\xd1\\\xf76\xe0c\xb4|C\xe9Pk\xd8r\xeeS\xe9!\xc5\xfc\xc7\xb7\xde\\v\xbcu\x99\x94\x10\x86J\x10\xc4\xef}\x8d\xcf,K\xc4_\xe5\xf6\xfe\xb7\xa1\xac\xe9\xb0\xbew-\xbev\xc8^\xd3Co\xb4\xba\xd8\xe46\x9eg2t\x04\x06\xf4-Y\x1b\xb2g\xf2\x8b\xe6+\xde\x01t)ZR>\x9d\xfc\xa0\xf5\x13\xb0\xfeDq_\xbb\xfd\x01(Q:#m\x80-\x0cg:b\x8ePG\xd3\xa7wO\x01\xea+\xee.\x01_\xfanX\xf6\n\x9dh\x82X!\x8c\x11\xd1b\xab\xeb\xfeBT\xb4\xe3\x99\x1e\x80\xda&\x1e\x17`\'\xa1\x92\xe7 L\x8c\xad^Mw\xd8v\xab\xfe\x1au\xa1}\xa8IS?k\xac\x0c\xee+\x03\x87\xfb\xbf\x93\xdc\x99\x1ft\xce\xe2v`\xd4\xc5\xac\x00\xa4\xbb\x92\xe2\xa1\xcaW!\xc2\xc9\xad\xfe\xf5X\xb2;\x8d\x0e\x1e\xc8O\x12\xd2`(*\x1f\xad\xad-\xa5\xbe\x0c\xc78\xfb\xa4)\x12w\xbd\\\xe3\xaa\x84m\xcc\x0c\xe5\x8a<\x0f\xa6t\x86_\n\xe2\xd9z\x07\xbcJ\xf5\x05\x12\x91q\t4\xdb\xfd\x1f\xb5\x8d\x9c\xeee\xc6\xbeN\n\x845\x16\xb7\xb0\xc6\xb8~s\x82DQ\xc3\x9d\x12\xfa\xf6J\xd0\xc5\xf4\xce\x16\x18\xa7\x8f\xd2*\x8bT&\x0b\xdcB\xfc\xeb\xfbD\x01\xf7\x89Is\xa5e\x18"\xc9\xcd\x9e\xf0{\xff\x03\xc5\xaeo\x99j\xfe\xd3Ly\x1a\xa7\xc2\xbf\xc9\x1dy\xbc\x7fm9\x03V\xe9\xd8R\xa6\x88\xb37uEn\x8b\xda\xd88P\xe1')
|
||||
3
src/wifi_config.py
Normal file
3
src/wifi_config.py
Normal file
File diff suppressed because one or more lines are too long
3
src/wsgi.py
Normal file
3
src/wsgi.py
Normal file
@ -0,0 +1,3 @@
|
||||
# Pyarmor 9.0.7 (trial), 000000, non-profits, 2025-03-05T12:22:14.586715
|
||||
from pyarmor_runtime_000000 import __pyarmor__
|
||||
__pyarmor__(__name__, __file__, b'PY000000\x00\x03\n\x00o\r\r\n\x80\x00\x01\x00\x08\x00\x00\x00\x04\x00\x00\x00@\x00\x00\x00\x9a\x01\x00\x00\x12\t\x04\x00\xc2\x16\xeb\xdb\x01#\xb1\xd9\xc2\xe2\xf6A^\xf4\xda\x89\x00\x00\x00\x00\x00\x00\x00\x00s\r\xc6\x00\xc4\xb3\x81\'\xb2|yB\xebs\x12\xecdEy\x82S(\xce\xce\x18\xb7\x9e\x08\x99\xf4\xf0]\x863\xe9h\xd8\x98n9O\xf5\xe2\xbf\x16\xd6\xcb\x18p\xc7\xf5\x9b- \x1aY\xdb\xa2Iu\xd5\xe14\xa4As\xb8\xa3t\x1a\xbfB\xce%\x8au\x84\x8b=\x85\x054\x14|\x8c\x00]\xe2)R\xed\xae\xda>\x04U\xceJ:\xd8\x1dW\xfdf\xb6\x1b\x81F\x0b\xd0Oany\xf3\x1e\xf3k\x9f\xbb\xf9\x10i[y\xdbP;\x89\x0c\xa7\xb2\xa2\x91\xf1e\xd5\xd9\xce9fz\xbe\x03\x8dfq\x064\xf4\x1a\x99s\xbf\x08X\x82W\x1ey`^^X\x1ai\xef\xa3\x0bx\xf3\x16K\x106T\x0eOA\x10\xa7{\x9fV\x95\x9d\xc7\xbc\x1d(\xe57\x95\xea\xc4\x02w\x8bu\xe3\x15\x8ea\x7f\xe77\x96\x03\x8c\x08"\xf6\x92\xc3;1\xa8\x919w\xf6g\x1a\x15\xa6Ci\xec=\xee_\x03\x03\x97\xcfl\x9b\xfb\x00\xee\xd0\x1b\xb7\xdb\x9bh\xbe\xa9\x8dJjK\xe4\xab\xe8\xa3<3\x82\x9f\xb2\xb2\x1d\xda\xfd\x13\xb3\xcc\xd8z\xfce\x13#~e\x9a\x11bD\xe8\x91\x82V\xff\x15\xb6\xf3\x8c\xe6zw\xf9\xf5U\x88$\xbc\xef-T\x01\x91R\xec-\xfb;\x8f\xc2\xbdtI\x7f\x98\x88\xbe+\xcd\xca\x9f\x01v\x99T\x9a\x10iJ\xfdo\xdf\x03\xe8\xec\xb8,\x99\xd7\xea\x1c0j\xbc\x18\x9fO;\xdf\x89X\x94>"\xe6\xa6\xd7U\t\xaa\xca\xef\xf0\xda\xd8\xdf\xd6\xc2*\xb9C\xf8\xfcm#z\xc9:\x85+{5\xa3<\xcd\xb2\x94M/\x80\x823u\x06\x7fI\xae\xf5\xc2\xc1\x15\xaf\x9c\xc4Yq\x86|\xd0\x8a')
|
||||
107
static/css/styles.css
Normal file
107
static/css/styles.css
Normal file
@ -0,0 +1,107 @@
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
width: 100%;
|
||||
background-color: black;
|
||||
border-bottom: 2px solid white;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
box-sizing: border-box; /* Ensure padding and border are included in the width */
|
||||
}
|
||||
|
||||
.navbar-left {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.navbar ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative; /* Ensure relative positioning for the submenu */
|
||||
}
|
||||
|
||||
.navbar ul li {
|
||||
float: left;
|
||||
position: relative; /* Ensure relative positioning for the submenu */
|
||||
}
|
||||
|
||||
.navbar ul li a {
|
||||
display: block;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 14px 16px;
|
||||
text-decoration: none;
|
||||
border-right: 1px solid white;
|
||||
}
|
||||
|
||||
.navbar ul li a:hover {
|
||||
background-color: grey;
|
||||
}
|
||||
|
||||
.navbar ul li a.disabled {
|
||||
color: grey;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.navbar ul .submenu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
background-color: black;
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-top: 2px solid white;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.navbar ul .submenu li {
|
||||
float: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.navbar ul .submenu li a {
|
||||
padding: 10px 16px;
|
||||
border-bottom: 1px solid white;
|
||||
}
|
||||
|
||||
.navbar ul .submenu li a:hover {
|
||||
background-color: grey;
|
||||
}
|
||||
|
||||
.navbar ul li:hover > .submenu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
.nav-image {
|
||||
height: 40px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
box-sizing: border-box; /* Ensure padding and border are included in the width */
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 90%; /* Increased width */
|
||||
max-width: 1400px; /* Increased max-width */
|
||||
text-align: center;
|
||||
box-sizing: border-box; /* Ensure padding and border are included in the width */
|
||||
}
|
||||
|
||||
.content h1 {
|
||||
color: black;
|
||||
}
|
||||
8030
static/fontawesome/css/all.css
vendored
Normal file
8030
static/fontawesome/css/all.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9
static/fontawesome/css/all.min.css
vendored
Normal file
9
static/fontawesome/css/all.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1594
static/fontawesome/css/brands.css
vendored
Normal file
1594
static/fontawesome/css/brands.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
static/fontawesome/css/brands.min.css
vendored
Normal file
6
static/fontawesome/css/brands.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
6375
static/fontawesome/css/fontawesome.css
vendored
Normal file
6375
static/fontawesome/css/fontawesome.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9
static/fontawesome/css/fontawesome.min.css
vendored
Normal file
9
static/fontawesome/css/fontawesome.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
19
static/fontawesome/css/regular.css
vendored
Normal file
19
static/fontawesome/css/regular.css
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2024 Fonticons, Inc.
|
||||
*/
|
||||
:root, :host {
|
||||
--fa-style-family-classic: 'Font Awesome 6 Free';
|
||||
--fa-font-regular: normal 400 1em/1 'Font Awesome 6 Free'; }
|
||||
|
||||
@font-face {
|
||||
font-family: 'Font Awesome 6 Free';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: block;
|
||||
src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); }
|
||||
|
||||
.far,
|
||||
.fa-regular {
|
||||
font-weight: 400; }
|
||||
6
static/fontawesome/css/regular.min.css
vendored
Normal file
6
static/fontawesome/css/regular.min.css
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2024 Fonticons, Inc.
|
||||
*/
|
||||
:host,:root{--fa-style-family-classic:"Font Awesome 6 Free";--fa-font-regular:normal 400 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype")}.fa-regular,.far{font-weight:400}
|
||||
19
static/fontawesome/css/solid.css
vendored
Normal file
19
static/fontawesome/css/solid.css
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2024 Fonticons, Inc.
|
||||
*/
|
||||
:root, :host {
|
||||
--fa-style-family-classic: 'Font Awesome 6 Free';
|
||||
--fa-font-solid: normal 900 1em/1 'Font Awesome 6 Free'; }
|
||||
|
||||
@font-face {
|
||||
font-family: 'Font Awesome 6 Free';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
font-display: block;
|
||||
src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }
|
||||
|
||||
.fas,
|
||||
.fa-solid {
|
||||
font-weight: 900; }
|
||||
6
static/fontawesome/css/solid.min.css
vendored
Normal file
6
static/fontawesome/css/solid.min.css
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2024 Fonticons, Inc.
|
||||
*/
|
||||
:host,:root{--fa-style-family-classic:"Font Awesome 6 Free";--fa-font-solid:normal 900 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}.fa-solid,.fas{font-weight:900}
|
||||
640
static/fontawesome/css/svg-with-js.css
vendored
Normal file
640
static/fontawesome/css/svg-with-js.css
vendored
Normal file
@ -0,0 +1,640 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2024 Fonticons, Inc.
|
||||
*/
|
||||
:root, :host {
|
||||
--fa-font-solid: normal 900 1em/1 'Font Awesome 6 Solid';
|
||||
--fa-font-regular: normal 400 1em/1 'Font Awesome 6 Regular';
|
||||
--fa-font-light: normal 300 1em/1 'Font Awesome 6 Light';
|
||||
--fa-font-thin: normal 100 1em/1 'Font Awesome 6 Thin';
|
||||
--fa-font-duotone: normal 900 1em/1 'Font Awesome 6 Duotone';
|
||||
--fa-font-sharp-solid: normal 900 1em/1 'Font Awesome 6 Sharp';
|
||||
--fa-font-sharp-regular: normal 400 1em/1 'Font Awesome 6 Sharp';
|
||||
--fa-font-sharp-light: normal 300 1em/1 'Font Awesome 6 Sharp';
|
||||
--fa-font-sharp-thin: normal 100 1em/1 'Font Awesome 6 Sharp';
|
||||
--fa-font-brands: normal 400 1em/1 'Font Awesome 6 Brands'; }
|
||||
|
||||
svg:not(:root).svg-inline--fa, svg:not(:host).svg-inline--fa {
|
||||
overflow: visible;
|
||||
box-sizing: content-box; }
|
||||
|
||||
.svg-inline--fa {
|
||||
display: var(--fa-display, inline-block);
|
||||
height: 1em;
|
||||
overflow: visible;
|
||||
vertical-align: -.125em; }
|
||||
.svg-inline--fa.fa-2xs {
|
||||
vertical-align: 0.1em; }
|
||||
.svg-inline--fa.fa-xs {
|
||||
vertical-align: 0em; }
|
||||
.svg-inline--fa.fa-sm {
|
||||
vertical-align: -0.07143em; }
|
||||
.svg-inline--fa.fa-lg {
|
||||
vertical-align: -0.2em; }
|
||||
.svg-inline--fa.fa-xl {
|
||||
vertical-align: -0.25em; }
|
||||
.svg-inline--fa.fa-2xl {
|
||||
vertical-align: -0.3125em; }
|
||||
.svg-inline--fa.fa-pull-left {
|
||||
margin-right: var(--fa-pull-margin, 0.3em);
|
||||
width: auto; }
|
||||
.svg-inline--fa.fa-pull-right {
|
||||
margin-left: var(--fa-pull-margin, 0.3em);
|
||||
width: auto; }
|
||||
.svg-inline--fa.fa-li {
|
||||
width: var(--fa-li-width, 2em);
|
||||
top: 0.25em; }
|
||||
.svg-inline--fa.fa-fw {
|
||||
width: var(--fa-fw-width, 1.25em); }
|
||||
|
||||
.fa-layers svg.svg-inline--fa {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0; }
|
||||
|
||||
.fa-layers-text, .fa-layers-counter {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
text-align: center; }
|
||||
|
||||
.fa-layers {
|
||||
display: inline-block;
|
||||
height: 1em;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
vertical-align: -.125em;
|
||||
width: 1em; }
|
||||
.fa-layers svg.svg-inline--fa {
|
||||
-webkit-transform-origin: center center;
|
||||
transform-origin: center center; }
|
||||
|
||||
.fa-layers-text {
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
-webkit-transform-origin: center center;
|
||||
transform-origin: center center; }
|
||||
|
||||
.fa-layers-counter {
|
||||
background-color: var(--fa-counter-background-color, #ff253a);
|
||||
border-radius: var(--fa-counter-border-radius, 1em);
|
||||
box-sizing: border-box;
|
||||
color: var(--fa-inverse, #fff);
|
||||
line-height: var(--fa-counter-line-height, 1);
|
||||
max-width: var(--fa-counter-max-width, 5em);
|
||||
min-width: var(--fa-counter-min-width, 1.5em);
|
||||
overflow: hidden;
|
||||
padding: var(--fa-counter-padding, 0.25em 0.5em);
|
||||
right: var(--fa-right, 0);
|
||||
text-overflow: ellipsis;
|
||||
top: var(--fa-top, 0);
|
||||
-webkit-transform: scale(var(--fa-counter-scale, 0.25));
|
||||
transform: scale(var(--fa-counter-scale, 0.25));
|
||||
-webkit-transform-origin: top right;
|
||||
transform-origin: top right; }
|
||||
|
||||
.fa-layers-bottom-right {
|
||||
bottom: var(--fa-bottom, 0);
|
||||
right: var(--fa-right, 0);
|
||||
top: auto;
|
||||
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
|
||||
transform: scale(var(--fa-layers-scale, 0.25));
|
||||
-webkit-transform-origin: bottom right;
|
||||
transform-origin: bottom right; }
|
||||
|
||||
.fa-layers-bottom-left {
|
||||
bottom: var(--fa-bottom, 0);
|
||||
left: var(--fa-left, 0);
|
||||
right: auto;
|
||||
top: auto;
|
||||
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
|
||||
transform: scale(var(--fa-layers-scale, 0.25));
|
||||
-webkit-transform-origin: bottom left;
|
||||
transform-origin: bottom left; }
|
||||
|
||||
.fa-layers-top-right {
|
||||
top: var(--fa-top, 0);
|
||||
right: var(--fa-right, 0);
|
||||
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
|
||||
transform: scale(var(--fa-layers-scale, 0.25));
|
||||
-webkit-transform-origin: top right;
|
||||
transform-origin: top right; }
|
||||
|
||||
.fa-layers-top-left {
|
||||
left: var(--fa-left, 0);
|
||||
right: auto;
|
||||
top: var(--fa-top, 0);
|
||||
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
|
||||
transform: scale(var(--fa-layers-scale, 0.25));
|
||||
-webkit-transform-origin: top left;
|
||||
transform-origin: top left; }
|
||||
|
||||
.fa-1x {
|
||||
font-size: 1em; }
|
||||
|
||||
.fa-2x {
|
||||
font-size: 2em; }
|
||||
|
||||
.fa-3x {
|
||||
font-size: 3em; }
|
||||
|
||||
.fa-4x {
|
||||
font-size: 4em; }
|
||||
|
||||
.fa-5x {
|
||||
font-size: 5em; }
|
||||
|
||||
.fa-6x {
|
||||
font-size: 6em; }
|
||||
|
||||
.fa-7x {
|
||||
font-size: 7em; }
|
||||
|
||||
.fa-8x {
|
||||
font-size: 8em; }
|
||||
|
||||
.fa-9x {
|
||||
font-size: 9em; }
|
||||
|
||||
.fa-10x {
|
||||
font-size: 10em; }
|
||||
|
||||
.fa-2xs {
|
||||
font-size: 0.625em;
|
||||
line-height: 0.1em;
|
||||
vertical-align: 0.225em; }
|
||||
|
||||
.fa-xs {
|
||||
font-size: 0.75em;
|
||||
line-height: 0.08333em;
|
||||
vertical-align: 0.125em; }
|
||||
|
||||
.fa-sm {
|
||||
font-size: 0.875em;
|
||||
line-height: 0.07143em;
|
||||
vertical-align: 0.05357em; }
|
||||
|
||||
.fa-lg {
|
||||
font-size: 1.25em;
|
||||
line-height: 0.05em;
|
||||
vertical-align: -0.075em; }
|
||||
|
||||
.fa-xl {
|
||||
font-size: 1.5em;
|
||||
line-height: 0.04167em;
|
||||
vertical-align: -0.125em; }
|
||||
|
||||
.fa-2xl {
|
||||
font-size: 2em;
|
||||
line-height: 0.03125em;
|
||||
vertical-align: -0.1875em; }
|
||||
|
||||
.fa-fw {
|
||||
text-align: center;
|
||||
width: 1.25em; }
|
||||
|
||||
.fa-ul {
|
||||
list-style-type: none;
|
||||
margin-left: var(--fa-li-margin, 2.5em);
|
||||
padding-left: 0; }
|
||||
.fa-ul > li {
|
||||
position: relative; }
|
||||
|
||||
.fa-li {
|
||||
left: calc(var(--fa-li-width, 2em) * -1);
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: var(--fa-li-width, 2em);
|
||||
line-height: inherit; }
|
||||
|
||||
.fa-border {
|
||||
border-color: var(--fa-border-color, #eee);
|
||||
border-radius: var(--fa-border-radius, 0.1em);
|
||||
border-style: var(--fa-border-style, solid);
|
||||
border-width: var(--fa-border-width, 0.08em);
|
||||
padding: var(--fa-border-padding, 0.2em 0.25em 0.15em); }
|
||||
|
||||
.fa-pull-left {
|
||||
float: left;
|
||||
margin-right: var(--fa-pull-margin, 0.3em); }
|
||||
|
||||
.fa-pull-right {
|
||||
float: right;
|
||||
margin-left: var(--fa-pull-margin, 0.3em); }
|
||||
|
||||
.fa-beat {
|
||||
-webkit-animation-name: fa-beat;
|
||||
animation-name: fa-beat;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out);
|
||||
animation-timing-function: var(--fa-animation-timing, ease-in-out); }
|
||||
|
||||
.fa-bounce {
|
||||
-webkit-animation-name: fa-bounce;
|
||||
animation-name: fa-bounce;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1));
|
||||
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1)); }
|
||||
|
||||
.fa-fade {
|
||||
-webkit-animation-name: fa-fade;
|
||||
animation-name: fa-fade;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
|
||||
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); }
|
||||
|
||||
.fa-beat-fade {
|
||||
-webkit-animation-name: fa-beat-fade;
|
||||
animation-name: fa-beat-fade;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
|
||||
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); }
|
||||
|
||||
.fa-flip {
|
||||
-webkit-animation-name: fa-flip;
|
||||
animation-name: fa-flip;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out);
|
||||
animation-timing-function: var(--fa-animation-timing, ease-in-out); }
|
||||
|
||||
.fa-shake {
|
||||
-webkit-animation-name: fa-shake;
|
||||
animation-name: fa-shake;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, linear);
|
||||
animation-timing-function: var(--fa-animation-timing, linear); }
|
||||
|
||||
.fa-spin {
|
||||
-webkit-animation-name: fa-spin;
|
||||
animation-name: fa-spin;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 2s);
|
||||
animation-duration: var(--fa-animation-duration, 2s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, linear);
|
||||
animation-timing-function: var(--fa-animation-timing, linear); }
|
||||
|
||||
.fa-spin-reverse {
|
||||
--fa-animation-direction: reverse; }
|
||||
|
||||
.fa-pulse,
|
||||
.fa-spin-pulse {
|
||||
-webkit-animation-name: fa-spin;
|
||||
animation-name: fa-spin;
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, steps(8));
|
||||
animation-timing-function: var(--fa-animation-timing, steps(8)); }
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.fa-beat,
|
||||
.fa-bounce,
|
||||
.fa-fade,
|
||||
.fa-beat-fade,
|
||||
.fa-flip,
|
||||
.fa-pulse,
|
||||
.fa-shake,
|
||||
.fa-spin,
|
||||
.fa-spin-pulse {
|
||||
-webkit-animation-delay: -1ms;
|
||||
animation-delay: -1ms;
|
||||
-webkit-animation-duration: 1ms;
|
||||
animation-duration: 1ms;
|
||||
-webkit-animation-iteration-count: 1;
|
||||
animation-iteration-count: 1;
|
||||
-webkit-transition-delay: 0s;
|
||||
transition-delay: 0s;
|
||||
-webkit-transition-duration: 0s;
|
||||
transition-duration: 0s; } }
|
||||
|
||||
@-webkit-keyframes fa-beat {
|
||||
0%, 90% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1); }
|
||||
45% {
|
||||
-webkit-transform: scale(var(--fa-beat-scale, 1.25));
|
||||
transform: scale(var(--fa-beat-scale, 1.25)); } }
|
||||
|
||||
@keyframes fa-beat {
|
||||
0%, 90% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1); }
|
||||
45% {
|
||||
-webkit-transform: scale(var(--fa-beat-scale, 1.25));
|
||||
transform: scale(var(--fa-beat-scale, 1.25)); } }
|
||||
|
||||
@-webkit-keyframes fa-bounce {
|
||||
0% {
|
||||
-webkit-transform: scale(1, 1) translateY(0);
|
||||
transform: scale(1, 1) translateY(0); }
|
||||
10% {
|
||||
-webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
|
||||
transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); }
|
||||
30% {
|
||||
-webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
|
||||
transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); }
|
||||
50% {
|
||||
-webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
|
||||
transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); }
|
||||
57% {
|
||||
-webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
|
||||
transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); }
|
||||
64% {
|
||||
-webkit-transform: scale(1, 1) translateY(0);
|
||||
transform: scale(1, 1) translateY(0); }
|
||||
100% {
|
||||
-webkit-transform: scale(1, 1) translateY(0);
|
||||
transform: scale(1, 1) translateY(0); } }
|
||||
|
||||
@keyframes fa-bounce {
|
||||
0% {
|
||||
-webkit-transform: scale(1, 1) translateY(0);
|
||||
transform: scale(1, 1) translateY(0); }
|
||||
10% {
|
||||
-webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
|
||||
transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); }
|
||||
30% {
|
||||
-webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
|
||||
transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); }
|
||||
50% {
|
||||
-webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
|
||||
transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); }
|
||||
57% {
|
||||
-webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
|
||||
transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); }
|
||||
64% {
|
||||
-webkit-transform: scale(1, 1) translateY(0);
|
||||
transform: scale(1, 1) translateY(0); }
|
||||
100% {
|
||||
-webkit-transform: scale(1, 1) translateY(0);
|
||||
transform: scale(1, 1) translateY(0); } }
|
||||
|
||||
@-webkit-keyframes fa-fade {
|
||||
50% {
|
||||
opacity: var(--fa-fade-opacity, 0.4); } }
|
||||
|
||||
@keyframes fa-fade {
|
||||
50% {
|
||||
opacity: var(--fa-fade-opacity, 0.4); } }
|
||||
|
||||
@-webkit-keyframes fa-beat-fade {
|
||||
0%, 100% {
|
||||
opacity: var(--fa-beat-fade-opacity, 0.4);
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1); }
|
||||
50% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale(var(--fa-beat-fade-scale, 1.125));
|
||||
transform: scale(var(--fa-beat-fade-scale, 1.125)); } }
|
||||
|
||||
@keyframes fa-beat-fade {
|
||||
0%, 100% {
|
||||
opacity: var(--fa-beat-fade-opacity, 0.4);
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1); }
|
||||
50% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale(var(--fa-beat-fade-scale, 1.125));
|
||||
transform: scale(var(--fa-beat-fade-scale, 1.125)); } }
|
||||
|
||||
@-webkit-keyframes fa-flip {
|
||||
50% {
|
||||
-webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
|
||||
transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); } }
|
||||
|
||||
@keyframes fa-flip {
|
||||
50% {
|
||||
-webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
|
||||
transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); } }
|
||||
|
||||
@-webkit-keyframes fa-shake {
|
||||
0% {
|
||||
-webkit-transform: rotate(-15deg);
|
||||
transform: rotate(-15deg); }
|
||||
4% {
|
||||
-webkit-transform: rotate(15deg);
|
||||
transform: rotate(15deg); }
|
||||
8%, 24% {
|
||||
-webkit-transform: rotate(-18deg);
|
||||
transform: rotate(-18deg); }
|
||||
12%, 28% {
|
||||
-webkit-transform: rotate(18deg);
|
||||
transform: rotate(18deg); }
|
||||
16% {
|
||||
-webkit-transform: rotate(-22deg);
|
||||
transform: rotate(-22deg); }
|
||||
20% {
|
||||
-webkit-transform: rotate(22deg);
|
||||
transform: rotate(22deg); }
|
||||
32% {
|
||||
-webkit-transform: rotate(-12deg);
|
||||
transform: rotate(-12deg); }
|
||||
36% {
|
||||
-webkit-transform: rotate(12deg);
|
||||
transform: rotate(12deg); }
|
||||
40%, 100% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg); } }
|
||||
|
||||
@keyframes fa-shake {
|
||||
0% {
|
||||
-webkit-transform: rotate(-15deg);
|
||||
transform: rotate(-15deg); }
|
||||
4% {
|
||||
-webkit-transform: rotate(15deg);
|
||||
transform: rotate(15deg); }
|
||||
8%, 24% {
|
||||
-webkit-transform: rotate(-18deg);
|
||||
transform: rotate(-18deg); }
|
||||
12%, 28% {
|
||||
-webkit-transform: rotate(18deg);
|
||||
transform: rotate(18deg); }
|
||||
16% {
|
||||
-webkit-transform: rotate(-22deg);
|
||||
transform: rotate(-22deg); }
|
||||
20% {
|
||||
-webkit-transform: rotate(22deg);
|
||||
transform: rotate(22deg); }
|
||||
32% {
|
||||
-webkit-transform: rotate(-12deg);
|
||||
transform: rotate(-12deg); }
|
||||
36% {
|
||||
-webkit-transform: rotate(12deg);
|
||||
transform: rotate(12deg); }
|
||||
40%, 100% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg); } }
|
||||
|
||||
@-webkit-keyframes fa-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg); }
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg); } }
|
||||
|
||||
@keyframes fa-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg); }
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg); } }
|
||||
|
||||
.fa-rotate-90 {
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg); }
|
||||
|
||||
.fa-rotate-180 {
|
||||
-webkit-transform: rotate(180deg);
|
||||
transform: rotate(180deg); }
|
||||
|
||||
.fa-rotate-270 {
|
||||
-webkit-transform: rotate(270deg);
|
||||
transform: rotate(270deg); }
|
||||
|
||||
.fa-flip-horizontal {
|
||||
-webkit-transform: scale(-1, 1);
|
||||
transform: scale(-1, 1); }
|
||||
|
||||
.fa-flip-vertical {
|
||||
-webkit-transform: scale(1, -1);
|
||||
transform: scale(1, -1); }
|
||||
|
||||
.fa-flip-both,
|
||||
.fa-flip-horizontal.fa-flip-vertical {
|
||||
-webkit-transform: scale(-1, -1);
|
||||
transform: scale(-1, -1); }
|
||||
|
||||
.fa-rotate-by {
|
||||
-webkit-transform: rotate(var(--fa-rotate-angle, 0));
|
||||
transform: rotate(var(--fa-rotate-angle, 0)); }
|
||||
|
||||
.fa-stack {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
height: 2em;
|
||||
position: relative;
|
||||
width: 2.5em; }
|
||||
|
||||
.fa-stack-1x,
|
||||
.fa-stack-2x {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: var(--fa-stack-z-index, auto); }
|
||||
|
||||
.svg-inline--fa.fa-stack-1x {
|
||||
height: 1em;
|
||||
width: 1.25em; }
|
||||
|
||||
.svg-inline--fa.fa-stack-2x {
|
||||
height: 2em;
|
||||
width: 2.5em; }
|
||||
|
||||
.fa-inverse {
|
||||
color: var(--fa-inverse, #fff); }
|
||||
|
||||
.sr-only,
|
||||
.fa-sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0; }
|
||||
|
||||
.sr-only-focusable:not(:focus),
|
||||
.fa-sr-only-focusable:not(:focus) {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0; }
|
||||
|
||||
.svg-inline--fa .fa-primary {
|
||||
fill: var(--fa-primary-color, currentColor);
|
||||
opacity: var(--fa-primary-opacity, 1); }
|
||||
|
||||
.svg-inline--fa .fa-secondary {
|
||||
fill: var(--fa-secondary-color, currentColor);
|
||||
opacity: var(--fa-secondary-opacity, 0.4); }
|
||||
|
||||
.svg-inline--fa.fa-swap-opacity .fa-primary {
|
||||
opacity: var(--fa-secondary-opacity, 0.4); }
|
||||
|
||||
.svg-inline--fa.fa-swap-opacity .fa-secondary {
|
||||
opacity: var(--fa-primary-opacity, 1); }
|
||||
|
||||
.svg-inline--fa mask .fa-primary,
|
||||
.svg-inline--fa mask .fa-secondary {
|
||||
fill: black; }
|
||||
|
||||
.fad.fa-inverse,
|
||||
.fa-duotone.fa-inverse {
|
||||
color: var(--fa-inverse, #fff); }
|
||||
6
static/fontawesome/css/svg-with-js.min.css
vendored
Normal file
6
static/fontawesome/css/svg-with-js.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
26
static/fontawesome/css/v4-font-face.css
vendored
Normal file
26
static/fontawesome/css/v4-font-face.css
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2024 Fonticons, Inc.
|
||||
*/
|
||||
@font-face {
|
||||
font-family: 'FontAwesome';
|
||||
font-display: block;
|
||||
src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }
|
||||
|
||||
@font-face {
|
||||
font-family: 'FontAwesome';
|
||||
font-display: block;
|
||||
src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); }
|
||||
|
||||
@font-face {
|
||||
font-family: 'FontAwesome';
|
||||
font-display: block;
|
||||
src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype");
|
||||
unicode-range: U+F003,U+F006,U+F014,U+F016-F017,U+F01A-F01B,U+F01D,U+F022,U+F03E,U+F044,U+F046,U+F05C-F05D,U+F06E,U+F070,U+F087-F088,U+F08A,U+F094,U+F096-F097,U+F09D,U+F0A0,U+F0A2,U+F0A4-F0A7,U+F0C5,U+F0C7,U+F0E5-F0E6,U+F0EB,U+F0F6-F0F8,U+F10C,U+F114-F115,U+F118-F11A,U+F11C-F11D,U+F133,U+F147,U+F14E,U+F150-F152,U+F185-F186,U+F18E,U+F190-F192,U+F196,U+F1C1-F1C9,U+F1D9,U+F1DB,U+F1E3,U+F1EA,U+F1F7,U+F1F9,U+F20A,U+F247-F248,U+F24A,U+F24D,U+F255-F25B,U+F25D,U+F271-F274,U+F278,U+F27B,U+F28C,U+F28E,U+F29C,U+F2B5,U+F2B7,U+F2BA,U+F2BC,U+F2BE,U+F2C0-F2C1,U+F2C3,U+F2D0,U+F2D2,U+F2D4,U+F2DC; }
|
||||
|
||||
@font-face {
|
||||
font-family: 'FontAwesome';
|
||||
font-display: block;
|
||||
src: url("../webfonts/fa-v4compatibility.woff2") format("woff2"), url("../webfonts/fa-v4compatibility.ttf") format("truetype");
|
||||
unicode-range: U+F041,U+F047,U+F065-F066,U+F07D-F07E,U+F080,U+F08B,U+F08E,U+F090,U+F09A,U+F0AC,U+F0AE,U+F0B2,U+F0D0,U+F0D6,U+F0E4,U+F0EC,U+F10A-F10B,U+F123,U+F13E,U+F148-F149,U+F14C,U+F156,U+F15E,U+F160-F161,U+F163,U+F175-F178,U+F195,U+F1F8,U+F219,U+F27A; }
|
||||
6
static/fontawesome/css/v4-font-face.min.css
vendored
Normal file
6
static/fontawesome/css/v4-font-face.min.css
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2024 Fonticons, Inc.
|
||||
*/
|
||||
@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype");unicode-range:u+f003,u+f006,u+f014,u+f016-f017,u+f01a-f01b,u+f01d,u+f022,u+f03e,u+f044,u+f046,u+f05c-f05d,u+f06e,u+f070,u+f087-f088,u+f08a,u+f094,u+f096-f097,u+f09d,u+f0a0,u+f0a2,u+f0a4-f0a7,u+f0c5,u+f0c7,u+f0e5-f0e6,u+f0eb,u+f0f6-f0f8,u+f10c,u+f114-f115,u+f118-f11a,u+f11c-f11d,u+f133,u+f147,u+f14e,u+f150-f152,u+f185-f186,u+f18e,u+f190-f192,u+f196,u+f1c1-f1c9,u+f1d9,u+f1db,u+f1e3,u+f1ea,u+f1f7,u+f1f9,u+f20a,u+f247-f248,u+f24a,u+f24d,u+f255-f25b,u+f25d,u+f271-f274,u+f278,u+f27b,u+f28c,u+f28e,u+f29c,u+f2b5,u+f2b7,u+f2ba,u+f2bc,u+f2be,u+f2c0-f2c1,u+f2c3,u+f2d0,u+f2d2,u+f2d4,u+f2dc}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-v4compatibility.woff2) format("woff2"),url(../webfonts/fa-v4compatibility.ttf) format("truetype");unicode-range:u+f041,u+f047,u+f065-f066,u+f07d-f07e,u+f080,u+f08b,u+f08e,u+f090,u+f09a,u+f0ac,u+f0ae,u+f0b2,u+f0d0,u+f0d6,u+f0e4,u+f0ec,u+f10a-f10b,u+f123,u+f13e,u+f148-f149,u+f14c,u+f156,u+f15e,u+f160-f161,u+f163,u+f175-f178,u+f195,u+f1f8,u+f219,u+f27a}
|
||||
2194
static/fontawesome/css/v4-shims.css
vendored
Normal file
2194
static/fontawesome/css/v4-shims.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
static/fontawesome/css/v4-shims.min.css
vendored
Normal file
6
static/fontawesome/css/v4-shims.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
22
static/fontawesome/css/v5-font-face.css
vendored
Normal file
22
static/fontawesome/css/v5-font-face.css
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2024 Fonticons, Inc.
|
||||
*/
|
||||
@font-face {
|
||||
font-family: 'Font Awesome 5 Brands';
|
||||
font-display: block;
|
||||
font-weight: 400;
|
||||
src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); }
|
||||
|
||||
@font-face {
|
||||
font-family: 'Font Awesome 5 Free';
|
||||
font-display: block;
|
||||
font-weight: 900;
|
||||
src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }
|
||||
|
||||
@font-face {
|
||||
font-family: 'Font Awesome 5 Free';
|
||||
font-display: block;
|
||||
font-weight: 400;
|
||||
src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); }
|
||||
6
static/fontawesome/css/v5-font-face.min.css
vendored
Normal file
6
static/fontawesome/css/v5-font-face.min.css
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2024 Fonticons, Inc.
|
||||
*/
|
||||
@font-face{font-family:"Font Awesome 5 Brands";font-display:block;font-weight:400;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:900;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:400;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype")}
|
||||
BIN
static/fontawesome/webfonts/fa-brands-400.ttf
Normal file
BIN
static/fontawesome/webfonts/fa-brands-400.ttf
Normal file
Binary file not shown.
BIN
static/fontawesome/webfonts/fa-brands-400.woff2
Normal file
BIN
static/fontawesome/webfonts/fa-brands-400.woff2
Normal file
Binary file not shown.
BIN
static/fontawesome/webfonts/fa-regular-400.ttf
Normal file
BIN
static/fontawesome/webfonts/fa-regular-400.ttf
Normal file
Binary file not shown.
BIN
static/fontawesome/webfonts/fa-regular-400.woff2
Normal file
BIN
static/fontawesome/webfonts/fa-regular-400.woff2
Normal file
Binary file not shown.
BIN
static/fontawesome/webfonts/fa-solid-900.ttf
Normal file
BIN
static/fontawesome/webfonts/fa-solid-900.ttf
Normal file
Binary file not shown.
BIN
static/fontawesome/webfonts/fa-solid-900.woff2
Normal file
BIN
static/fontawesome/webfonts/fa-solid-900.woff2
Normal file
Binary file not shown.
BIN
static/fontawesome/webfonts/fa-v4compatibility.ttf
Normal file
BIN
static/fontawesome/webfonts/fa-v4compatibility.ttf
Normal file
Binary file not shown.
BIN
static/fontawesome/webfonts/fa-v4compatibility.woff2
Normal file
BIN
static/fontawesome/webfonts/fa-v4compatibility.woff2
Normal file
Binary file not shown.
272
static/html/internet copy.html
Normal file
272
static/html/internet copy.html
Normal file
@ -0,0 +1,272 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>WiFi Configuration</title>
|
||||
<link rel="icon" type="image/x-icon" href="/static/images/favicon.ico">
|
||||
<link rel="stylesheet" href="/static/css/styles.css">
|
||||
<link rel="stylesheet" href="/static/fontawesome/css/all.min.css">
|
||||
<script src="/static/js/data-request.js"></script>
|
||||
<style>
|
||||
h1 {
|
||||
margin-top: 30px;
|
||||
font-size: 36px;
|
||||
color: #333;
|
||||
}
|
||||
.button-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.button-container .btn {
|
||||
padding: 10px 20px;
|
||||
font-size: 1.2em;
|
||||
cursor: pointer;
|
||||
background-color: blue;
|
||||
color: white;
|
||||
width: 120px;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
.button-container .btn:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
.scan-container {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.scan-container .btn {
|
||||
background-color: #28a745;
|
||||
}
|
||||
.scan-container .btn:hover {
|
||||
background-color: #218838;
|
||||
}
|
||||
.connect-container {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.connect-container .btn {
|
||||
padding:5px 15px;
|
||||
border-radius: 5px;
|
||||
background-color: #ffc107;
|
||||
}
|
||||
.connect-container .btn:hover {
|
||||
background-color: #e0a800;
|
||||
}
|
||||
.network-list {
|
||||
margin-top: 20px;
|
||||
width: 100%;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #ccc;
|
||||
background-color: white;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.network-list table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.network-list th, .network-list td {
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #ddd;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.network-list th {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
.network-list tr.selected {
|
||||
background-color: #d1e7dd;
|
||||
}
|
||||
|
||||
.status {
|
||||
margin-top: 20px;
|
||||
font-size: 18px;
|
||||
color: #555;
|
||||
}
|
||||
.home-btn {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
padding: 10px 20px;
|
||||
background-color: #6c757d;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.home-btn:hover {
|
||||
background-color: #5a6268;
|
||||
}
|
||||
.placeholder-img {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
.placeholder-img img {
|
||||
top: 20px;
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
}
|
||||
.header-img {
|
||||
margin-top: 20px; /* Adjust the margin as needed */
|
||||
margin-bottom: 30px;
|
||||
width: auto;
|
||||
height: 80px; /* Adjust the height as needed */
|
||||
position: absolute;
|
||||
left: 30px;
|
||||
top: 60px
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="navbar"></div>
|
||||
<script>
|
||||
fetch('/static/html/nav.html')
|
||||
.then(response => response.text())
|
||||
.then(data => {
|
||||
document.getElementById('navbar').innerHTML = data;
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="content-wrapper">
|
||||
<div class="content">
|
||||
<h1>WiFi Internet Access</h1>
|
||||
<img src="/static/images/internet_icon.png" alt="internet" class="header-img">
|
||||
<label id="label-status">Status:</label>
|
||||
<div class="button-container">
|
||||
<button class="btn" onclick="scanWifi()">Scan</button>
|
||||
<button class="btn" onclick="cancelScan()">Cancel</button>
|
||||
<button class="btn" onclick="forgetAll()">Forget All</button>
|
||||
<button class="btn" onclick="testInternet()">Test Internet</button>
|
||||
</div>
|
||||
<div class="scan-container">
|
||||
<div id="scanStatus" class="status"></div>
|
||||
</div>
|
||||
<div class="network-list">
|
||||
<table id="networksTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>SSID</th>
|
||||
<th>Freq</th>
|
||||
<th>Signal</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- List of networks will be appended here -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="connect-container">
|
||||
<button class="btn" onclick="connectToNetwork()">Connect</button>
|
||||
</div>
|
||||
<div class="status" id="connectionStatus"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.onload = function() { OnPageLoad(); };
|
||||
|
||||
function scanWifi() {
|
||||
console.log("Starting WiFi scan...");
|
||||
document.getElementById('scanStatus').innerText = "Scanning for networks...";
|
||||
fetch('/scan_wifi')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log("Scan complete. Data received:", data);
|
||||
document.getElementById('scanStatus').innerText = "Scan complete.";
|
||||
let tableBody = document.getElementById('networksTable').getElementsByTagName('tbody')[0];
|
||||
tableBody.innerHTML = '';
|
||||
data.networks.forEach(network => {
|
||||
let row = tableBody.insertRow();
|
||||
let cell1 = row.insertCell(0);
|
||||
let cell2 = row.insertCell(1);
|
||||
let cell3 = row.insertCell(2);
|
||||
cell1.textContent = network.ssid;
|
||||
cell2.textContent = network.Freq;
|
||||
cell3.textContent = network.signal;
|
||||
row.addEventListener('click', function() {
|
||||
const rows = document.querySelectorAll('#networksTable tbody tr');
|
||||
rows.forEach(r => r.classList.remove('selected'));
|
||||
row.classList.add('selected');
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error during scan:", error);
|
||||
document.getElementById('scanStatus').innerText = "Error during scan.";
|
||||
});
|
||||
}
|
||||
|
||||
function cancelScan() {
|
||||
console.log("Cancelling scan...");
|
||||
document.getElementById('scanStatus').innerText = "Scan cancelled.";
|
||||
}
|
||||
|
||||
function connectToNetwork() {
|
||||
console.log("Attempting to connect to network...");
|
||||
const table = document.getElementById('networksTable');
|
||||
const selectedRow = table.querySelector('tbody tr.selected');
|
||||
if (!selectedRow) {
|
||||
document.getElementById('connectionStatus').innerText = "Please select a network to connect to.";
|
||||
return;
|
||||
}
|
||||
const ssid = selectedRow.cells[0].textContent;
|
||||
const password = prompt("Enter the WiFi password for " + ssid + ":");
|
||||
if (!password) {
|
||||
document.getElementById('connectionStatus').innerText = "Connection cancelled.";
|
||||
return;
|
||||
}
|
||||
fetch('/connect_wifi', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ ssid: ssid, password: password })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log("Connection attempt result:", data);
|
||||
document.getElementById('connectionStatus').innerText = data.message;
|
||||
if (data.success) {
|
||||
checkInternetAccess();
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error during connection attempt:", error);
|
||||
document.getElementById('connectionStatus').innerText = "Error during connection attempt.";
|
||||
});
|
||||
}
|
||||
|
||||
function checkInternetAccess() {
|
||||
fetch('/check_internet_access')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const statusMessage = data.success ? "Internet Access Ok" : "No Internet Access";
|
||||
document.getElementById('connectionStatus').innerText = statusMessage;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error checking internet access:", error);
|
||||
document.getElementById('connectionStatus').innerText = "Error checking internet access.";
|
||||
});
|
||||
}
|
||||
|
||||
function OnPageLoad(){
|
||||
requestJsonFromServer('/get-status?param1=wifi-status')
|
||||
.then(data => {
|
||||
if (data !== null) {
|
||||
// expecting: {"msg":"message string"}
|
||||
console.log("Data received:", data);
|
||||
document.getElementById('label-status').innerText = data.msg;
|
||||
} else {
|
||||
console.log("Failed to retrieve data from the server.");
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
19
static/html/nav.html
Normal file
19
static/html/nav.html
Normal file
@ -0,0 +1,19 @@
|
||||
<nav class="navbar">
|
||||
<div class="navbar-left">
|
||||
<img src="/static/images/ata_logo.png" alt="Left Image" class="nav-image">
|
||||
</div>
|
||||
<ul>
|
||||
<li><a href="/"><i class="fas fa-home"></i> Home</a></li>
|
||||
<li><a href="/printio" target="_blank"><i class="fas fa-print"></i> Printio</a></li>
|
||||
<li><a href="/internet"><i class="fas fa-globe"></i> Internet</a></li>
|
||||
<!--<li><a href="#" class="disabled"><i class="fas fa-wifi"></i> Hotspot</a></li>-->
|
||||
<li>
|
||||
<a href="#"><i class="fas fa-cog"></i> System</a>
|
||||
<ul class="submenu">
|
||||
<!--<li><a href="/static/html/mediaconfig.html"><i class="fas fa-wrench"></i> Config</a></li>-->
|
||||
<li><a href="/static/html/power.html"><i class="fas fa-power-off"></i> Power</a></li>
|
||||
<li><a href="/about"><i class="fas fa-info-circle"></i> About</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
119
static/html/power.html
Normal file
119
static/html/power.html
Normal file
@ -0,0 +1,119 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Power Off System</title>
|
||||
<link rel="icon" type="image/x-icon" href="/static/images/favicon.ico">
|
||||
<link rel="stylesheet" href="/static/css/styles.css">
|
||||
<link rel="stylesheet" href="/static/fontawesome/css/all.min.css">
|
||||
<script src="/static/js/jquery-3.7.1.js"></script>
|
||||
<style>
|
||||
|
||||
.header-img {
|
||||
margin-top: 30px; /* Adjust the margin as needed */
|
||||
margin-bottom: 30px;
|
||||
width: auto;
|
||||
height: 70px; /* Adjust the height as needed */
|
||||
}
|
||||
.center-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
h1 {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
label, select, #media-sizes, button {
|
||||
margin: 5px 0;
|
||||
text-align: center;
|
||||
font-size: larger;
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
select {
|
||||
padding: 3px;
|
||||
font-size: 1.1em;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
#media-sizes ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#media-sizes li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#media-sizes input[type="checkbox"] {
|
||||
transform: scale(1.5);
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
#media-sizes span {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: red;
|
||||
color: white;
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
font-size: 1.2em;
|
||||
cursor: pointer;
|
||||
width: 150px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: darkblue;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="navbar"></div>
|
||||
<script>
|
||||
fetch('/static/html/nav.html')
|
||||
.then(response => response.text())
|
||||
.then(data => {
|
||||
document.getElementById('navbar').innerHTML = data;
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="content-wrapper">
|
||||
<div class="content center-content">
|
||||
<h1>Power Options</h1>
|
||||
<img src="/static/images/switch-icon.png" alt="cards" class="header-img">
|
||||
<button class="button" id="reboot-button">Reboot</button>
|
||||
<button class="button" id="shutdown-button">Shutdown</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#reboot-button').click(function() {
|
||||
$.post('/reboot', function(response) {
|
||||
alert("Reboot initiated");
|
||||
}).fail(function() {
|
||||
alert("Reboot failed");
|
||||
});
|
||||
});
|
||||
|
||||
$('#shutdown-button').click(function() {
|
||||
$.post('/shutdown', function(response) {
|
||||
alert("Shutdown initiated");
|
||||
}).fail(function() {
|
||||
alert("Shutdown failed");
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
23
static/html/status.html
Normal file
23
static/html/status.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Status</title>
|
||||
<link rel="stylesheet" href="/static/css/styles.css">
|
||||
<link rel="stylesheet" href="/static/fontawesome/css/all.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="navbar"></div>
|
||||
<div class="content">
|
||||
<h1>Status Page</h1>
|
||||
</div>
|
||||
<script>
|
||||
fetch('/static/html/nav.html')
|
||||
.then(response => response.text())
|
||||
.then(data => {
|
||||
document.getElementById('navbar').innerHTML = data;
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
BIN
static/images/ata_logo.png
Normal file
BIN
static/images/ata_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
static/images/favicon.ico
Normal file
BIN
static/images/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
BIN
static/images/helio-posh.png
Normal file
BIN
static/images/helio-posh.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
BIN
static/images/internet_icon.png
Normal file
BIN
static/images/internet_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
BIN
static/images/switch-icon.png
Normal file
BIN
static/images/switch-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.0 KiB |
1
static/js/crypto-js.min.js
vendored
Normal file
1
static/js/crypto-js.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
29
static/js/data-request.js
Normal file
29
static/js/data-request.js
Normal file
@ -0,0 +1,29 @@
|
||||
function requestJsonFromServer(route) {
|
||||
return fetch(route)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
return response.json(); // Assuming the server returns a JSON response
|
||||
})
|
||||
.then(jsonData => {
|
||||
//console.log('Received JSON data:', jsonData);
|
||||
return jsonData; // Return the JSON data
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('There was a problem with the fetch operation:', error);
|
||||
return null; // Return null in case of an error
|
||||
});
|
||||
}
|
||||
|
||||
/* Example usage
|
||||
requestJsonFromServer('/get_data')
|
||||
.then(data => {
|
||||
if (data !== null) {
|
||||
console.log("Data received:", data);
|
||||
// You can process the data here as needed
|
||||
} else {
|
||||
console.log("Failed to retrieve data from the server.");
|
||||
}
|
||||
});
|
||||
*/
|
||||
10716
static/js/jquery-3.7.1.js
vendored
Normal file
10716
static/js/jquery-3.7.1.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
77
static/js/printers copy.js
Normal file
77
static/js/printers copy.js
Normal file
@ -0,0 +1,77 @@
|
||||
$(document).ready(function() {
|
||||
console.log('Document is ready');
|
||||
|
||||
var printersData = [];
|
||||
|
||||
// Fetch printer data from the server when the page loads
|
||||
$.get('/get_printers', function(data) {
|
||||
console.log('Fetched printer data:', data);
|
||||
printersData = data;
|
||||
data.forEach(function(printer) {
|
||||
$('#printers').append(new Option(printer["display-name"], printer["display-name"]));
|
||||
});
|
||||
console.log('Printers dropdown populated');
|
||||
}).fail(function() {
|
||||
console.error('Failed to fetch printer data');
|
||||
});
|
||||
|
||||
// Handle printer selection change
|
||||
$('#printers').change(function() {
|
||||
var selectedPrinter = $(this).val();
|
||||
console.log('Printer selected:', selectedPrinter);
|
||||
if (selectedPrinter) {
|
||||
var printer = printersData.find(p => p["display-name"] === selectedPrinter);
|
||||
console.log('Selected printer data:', printer);
|
||||
if (printer) {
|
||||
var mediaSizesHtml = '<ul>';
|
||||
printer['media-sizes'].forEach(function(media) {
|
||||
mediaSizesHtml += '<li>';
|
||||
mediaSizesHtml += '<input type="checkbox" ' + (media.enabled ? 'checked' : '') + '>';
|
||||
mediaSizesHtml += '<span>' + media['media-size-display'] + ' - (' + media['capacity'] + ')' + '</span>';
|
||||
mediaSizesHtml += '</li>';
|
||||
});
|
||||
mediaSizesHtml += '</ul>';
|
||||
$('#media-sizes').html(mediaSizesHtml);
|
||||
console.log('Media sizes displayed for selected printer');
|
||||
}
|
||||
} else {
|
||||
$('#media-sizes').html('');
|
||||
console.log('No printer selected, media sizes cleared');
|
||||
}
|
||||
});
|
||||
|
||||
// Handle save button click
|
||||
$('#save').click(function() {
|
||||
var selectedPrinter = $('#printers').val();
|
||||
console.log('Save button clicked for printer:', selectedPrinter);
|
||||
if (selectedPrinter) {
|
||||
var printer = printersData.find(p => p["display-name"] === selectedPrinter);
|
||||
if (printer) {
|
||||
printer['media-sizes'] = [];
|
||||
$('#media-sizes li').each(function() {
|
||||
var enabled = $(this).find('input').is(':checked');
|
||||
var mediaSizeDisplay = $(this).find('span').text();
|
||||
var mediaSize = mediaSizeDisplay.match(/\(([^)]+)\)/)[1]; // Extract media-size from display text
|
||||
printer['media-sizes'].push({ "enabled": enabled, "media-size": mediaSize, "media-size-display": mediaSizeDisplay });
|
||||
});
|
||||
console.log('Updated printer data to be saved:', printersData);
|
||||
$.ajax({
|
||||
url: '/save_printers',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(printersData),
|
||||
success: function(response) {
|
||||
console.log('Save response:', response);
|
||||
alert('Changes saved successfully!');
|
||||
},
|
||||
error: function() {
|
||||
console.error('Failed to save changes');
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.warn('Please select a printer before saving');
|
||||
alert('Please select a printer.');
|
||||
}
|
||||
});
|
||||
});
|
||||
72
static/js/printers.js
Normal file
72
static/js/printers.js
Normal file
@ -0,0 +1,72 @@
|
||||
$(document).ready(function() {
|
||||
var printersData = [];
|
||||
|
||||
// Fetch printer data from the server when the page loads
|
||||
$.get('/get_printers', function(data) {
|
||||
printersData = data;
|
||||
data.forEach(function(printer) {
|
||||
$('#printers').append(new Option(printer["display-name"], printer["display-name"]));
|
||||
});
|
||||
}).fail(function() {
|
||||
console.error('Failed to fetch printer data');
|
||||
});
|
||||
|
||||
// Handle printer selection change
|
||||
$('#printers').change(function() {
|
||||
var selectedPrinter = $(this).val();
|
||||
if (selectedPrinter) {
|
||||
var printer = printersData.find(p => p["display-name"] === selectedPrinter);
|
||||
if (printer) {
|
||||
var mediaSizesHtml = '<ul>';
|
||||
printer['media-sizes'].forEach(function(media) {
|
||||
mediaSizesHtml += '<li>';
|
||||
mediaSizesHtml += '<input type="checkbox" ' + (media.enabled ? 'checked' : '') + '>';
|
||||
mediaSizesHtml += '<span>' + 'Size = ' + media['media-size-display'] + ' - cap = ' + media['capacity'] + '</span>';
|
||||
mediaSizesHtml += '</li>';
|
||||
});
|
||||
mediaSizesHtml += '</ul>';
|
||||
$('#media-sizes').html(mediaSizesHtml);
|
||||
}
|
||||
} else {
|
||||
$('#media-sizes').html('');
|
||||
}
|
||||
});
|
||||
|
||||
// Handle checkbox change event
|
||||
$(document).on('change', '#media-sizes input[type="checkbox"]', function() {
|
||||
var selectedPrinter = $('#printers').val();
|
||||
if (selectedPrinter) {
|
||||
var printer = printersData.find(p => p["display-name"] === selectedPrinter);
|
||||
if (printer) {
|
||||
$('#media-sizes li').each(function(index) {
|
||||
var enabled = $(this).find('input').is(':checked');
|
||||
printer['media-sizes'][index].enabled = enabled;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Handle save button click
|
||||
$('#save').click(function() {
|
||||
var selectedPrinter = $('#printers').val();
|
||||
if (selectedPrinter) {
|
||||
var printer = printersData.find(p => p["display-name"] === selectedPrinter);
|
||||
if (printer) {
|
||||
$.ajax({
|
||||
url: '/save_printers',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(printersData),
|
||||
success: function(response) {
|
||||
alert('Changes saved successfully!');
|
||||
},
|
||||
error: function() {
|
||||
console.error('Failed to save changes');
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
alert('Please select a printer.');
|
||||
}
|
||||
});
|
||||
});
|
||||
15
systemd/atadash.service
Normal file
15
systemd/atadash.service
Normal file
@ -0,0 +1,15 @@
|
||||
[Unit]
|
||||
Description=Gunicorn instance to serve atadash app
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=orangepi
|
||||
Group=www-data
|
||||
WorkingDirectory=/home/orangepi/atadash/src
|
||||
Environment="PATH=/home/orangepi/atadash/.venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
ExecStart=/home/orangepi/atadash/.venv/bin/gunicorn --workers 1 --bind unix:/home/orangepi/atadash/src/flaskapp.sock -m 007 wsgi:app
|
||||
ExecReload=/bin/kill -s HUP $MAINPID
|
||||
KillMode=mixed
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
11
systemd/command.txt
Normal file
11
systemd/command.txt
Normal file
@ -0,0 +1,11 @@
|
||||
# Start atadash service
|
||||
sudo ln -s /home/orangepi/atadash/systemd/atadash.service /etc/systemd/system/atadash.service
|
||||
sudo systemctl start atadash
|
||||
|
||||
PYTHONPATH=/home/orangepi/atadash/src /home/orangepi/atadash/.venv/bin/gunicorn --workers 1 --bind unix:/home/orangepi/atadash/src/flaskapp.sock -m 007 wsgi:app
|
||||
|
||||
|
||||
|
||||
#Start OverlayFS Mount service
|
||||
sudo ln -s /home/orangepi/atadash/systemd/overlayfs_mount.service /etc/systemd/system/overlayfs_mount.service
|
||||
sudo systemctl start overlayfs_mount
|
||||
16
systemd/overlayfs_mount.service
Normal file
16
systemd/overlayfs_mount.service
Normal file
@ -0,0 +1,16 @@
|
||||
[Unit]
|
||||
Description=Mount OverlayFS at Boot
|
||||
DefaultDependencies=no
|
||||
Before=sysinit.target local-fs.target
|
||||
Wants=local-fs-pre.target
|
||||
After=local-fs-pre.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/home/orangepi/atadash/bash/overlayfs_mount.sh
|
||||
RemainAfterExit=true
|
||||
user=root
|
||||
Group=root
|
||||
|
||||
[Install]
|
||||
WantedBy=sysinit.target
|
||||
181
templates/about.html
Normal file
181
templates/about.html
Normal file
@ -0,0 +1,181 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>About Printio</title>
|
||||
<link rel="icon" type="image/x-icon" href="/static/images/favicon.ico">
|
||||
<link rel="stylesheet" href="/static/css/styles.css">
|
||||
<link rel="stylesheet" href="/static/fontawesome/css/all.min.css">
|
||||
<style>
|
||||
h1 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
label, select, #media-sizes, button {
|
||||
margin: 5px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
select {
|
||||
padding: 3px;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
#media-sizes ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#media-sizes li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#media-sizes input[type="checkbox"] {
|
||||
transform: scale(1.5);
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
#media-sizes span {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: blue;
|
||||
color: white;
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
font-size: 1.2em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: darkblue;
|
||||
}
|
||||
|
||||
p {
|
||||
display: block;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.license-section {
|
||||
margin-top: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.license-status {
|
||||
font-size: 1.1em;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.license-input {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.license-input input {
|
||||
padding: 10px;
|
||||
width: 200px;
|
||||
font-size: 1.1em;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.license-input button {
|
||||
background-color: #4CAF50;
|
||||
padding: 10px 20px;
|
||||
font-size: 1.1em;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.license-input button:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
|
||||
/* New Styles for Layout */
|
||||
.content-wrapper {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.left-column {
|
||||
width: 280px;
|
||||
padding-right: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.right-column {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.license-box {
|
||||
padding: 15px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
}
|
||||
#p {
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="navbar"></div>
|
||||
<script>
|
||||
fetch('/static/html/nav.html')
|
||||
.then(response => response.text())
|
||||
.then(data => {
|
||||
document.getElementById('navbar').innerHTML = data;
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="content-wrapper">
|
||||
<div class="left-column">
|
||||
<div class="info-box">
|
||||
<h3>System Info</h3>
|
||||
<p>Version: {{info.software_version}}
|
||||
<p>CPU %: {{info.cpu}}</p>
|
||||
<p>CPU T: {{info.cpu_t}}</p>
|
||||
<p>Disk Size: {{info.disk_size}}</p>
|
||||
<p>Disk Used: {{info.disk_used}}</p>
|
||||
<p>RAM Size: {{info.ram_size}}</p>
|
||||
<p>RAM Used: {{info.ram_used}}</p>
|
||||
<p>Up Time: {{info.uptime}}</p>
|
||||
</div>
|
||||
|
||||
<div class="license-box">
|
||||
<h3>License Info </h3>
|
||||
<p>License: {{info.license}}</p>
|
||||
<!--p>Image Magic: {{info.image_magic}}</p-->
|
||||
<!--p>Hashtag: {{info.hash}}</p-->
|
||||
<!--p>Drop Folder: {{info.drop_folder}}</p-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right-column">
|
||||
<h1>About ATA Dash</h1>
|
||||
<p>
|
||||
ATA Dash is a simple interface to control your LCD Advertising display.
|
||||
</p>
|
||||
<p>
|
||||
Warning: Unauthorized reproduction or distribution of this product
|
||||
is strictly prohibited and may result in severe civil and criminal
|
||||
penalties.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
283
templates/index.html
Normal file
283
templates/index.html
Normal file
@ -0,0 +1,283 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Media Dashboard</title>
|
||||
<link rel="icon" type="image/x-icon" href="../static/images/favicon.ico">
|
||||
<link rel="stylesheet" href="../static/css/styles.css">
|
||||
<link rel="stylesheet" href="../static/fontawesome/css/all.min.css">
|
||||
<style>
|
||||
|
||||
h1 {
|
||||
margin-top: 20px;
|
||||
font-size: 36px;
|
||||
color: #333;
|
||||
}
|
||||
h2 {
|
||||
margin-top: 2px;
|
||||
font-size: 24px;
|
||||
color: #333;
|
||||
}
|
||||
.container {
|
||||
width: 80%;
|
||||
max-width: 300px;
|
||||
margin: 20px auto;
|
||||
padding: 20px;
|
||||
border: 2px solid #ccc;
|
||||
border-radius: 10px;
|
||||
background-color: #ffffffb6;
|
||||
position: relative;
|
||||
}
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.form-group input, .form-group select {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
font-size: 16px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.checkbox-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.checkbox-group input {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.button-group {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.button-group .btn {
|
||||
padding: 10px 20px;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
}
|
||||
.button-group .btn:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
.status {
|
||||
margin-top: 10px;
|
||||
font-size: 16px;
|
||||
color: #555;
|
||||
}
|
||||
.side-img {
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
left: 0;
|
||||
width: 230px; /* Set desired width */
|
||||
height: auto; /* Adjust height automatically to maintain aspect ratio */
|
||||
z-index: -1; /* Ensure image is behind other content */
|
||||
}
|
||||
.input-label{
|
||||
text-align: left;
|
||||
}
|
||||
.form-group textarea {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
font-size: 16px;
|
||||
box-sizing: border-box;
|
||||
resize: none; /* Prevents the user from resizing the textarea */
|
||||
overflow-wrap: break-word; /* Ensures that long URLs wrap to the next line */
|
||||
white-space: pre-wrap; /* Preserves whitespace and wraps text as necessary */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="navbar"></div>
|
||||
<script>
|
||||
fetch('/static/html/nav.html')
|
||||
.then(response => response.text())
|
||||
.then(data => {
|
||||
document.getElementById('navbar').innerHTML = data;
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="background-image"></div>
|
||||
|
||||
<!--<div><img src="/static/images/helio-posh.png" alt="Helio Posh" class="side-img"></div>-->
|
||||
<div class="content-wrapper">
|
||||
<div class="content">
|
||||
|
||||
<div>
|
||||
<img src="/static/images/helio-posh.png" alt="Helio Posh" class="side-img">
|
||||
</div>
|
||||
<h1>Media Dashboard</h1>
|
||||
<div class="container">
|
||||
<h2>Playlist Loop</h2>
|
||||
<div class="checkbox-group">
|
||||
<input type="checkbox" id="autoPlayAtBoot" name="autoPlayAtBoot" checked>
|
||||
<label for="autoPlayAtBoot">Autostart @Boot</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="input-label" for="mediaLocation">Media Sources:</label>
|
||||
<select id="mediaLocation" name="mediaLocation">
|
||||
<option value="USB">No Media Available</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="input-label" for="imageDuration">Image Duration in Secs:</label>
|
||||
<input type="number" id="imageDuration" name="imageDuration" min="1" max="60">
|
||||
</div>
|
||||
<div class="button-group">
|
||||
<button class="btn" onclick="startMediaLoop()">Start</button>
|
||||
<button class="btn" onclick="stopMediaLoop()">Stop</button>
|
||||
</div>
|
||||
<div class="status" id="mediaLoopStatus">status</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<h2>Web Gallery</h2>
|
||||
<div class="checkbox-group">
|
||||
<input type="checkbox" id="autoStart" name="autoStart" checked>
|
||||
<label for="autoStart">Autostart</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="btn" onclick="clearURL()">Clear</button>
|
||||
<label class="input-label" for="galleryURL">URL:</label>
|
||||
<textarea id="galleryURL" name="galleryURL" rows="3"></textarea>
|
||||
</div>
|
||||
<div class="button-group">
|
||||
<button class="btn" onclick="startWebGallery()">Start</button>
|
||||
<button class="btn" onclick="stopWebGallery()">Stop</button>
|
||||
</div>
|
||||
<div class="status" id="webGalleryStatus">status</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
function loadMediaSources() {
|
||||
fetch('../get_media_sources')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
media_sources = data.folders; // Access the "folders" array in the JSON
|
||||
const mediaLocationSelect = document.getElementById('mediaLocation');
|
||||
|
||||
// Clear any existing options
|
||||
while (mediaLocationSelect.options.length > 0) {
|
||||
mediaLocationSelect.remove(0);
|
||||
}
|
||||
|
||||
// Add new options
|
||||
media_sources.forEach(media => {
|
||||
var option = document.createElement('option');
|
||||
option.text = media.folder_name_display;
|
||||
option.value = media.folder_path;
|
||||
mediaLocationSelect.add(option);
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error loading media sources:", error);
|
||||
});
|
||||
}
|
||||
|
||||
function loadLastUsedData() {
|
||||
fetch('../get_screen_settings')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.info(data)
|
||||
document.getElementById('autoPlayAtBoot').checked = data.autoPlayAtBoot || true;
|
||||
document.getElementById('imageDuration').value = data.imageDuration || 5;
|
||||
document.getElementById('autoStart').checked = data.autoStart || true;
|
||||
document.getElementById('galleryURL').value = data.url || 'google.com';
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error loading screen settings:", error);
|
||||
});
|
||||
}
|
||||
|
||||
function startMediaLoop() {
|
||||
const mediaLocation = document.getElementById('mediaLocation').value;
|
||||
const imageDuration = document.getElementById('imageDuration').value;
|
||||
const autoPlayAtBoot = document.getElementById('autoPlayAtBoot').checked;
|
||||
|
||||
fetch('../start_media_loop', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ mediaLocation: mediaLocation, imageDuration: imageDuration , autoPlayAtBoot: autoPlayAtBoot})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
document.getElementById('mediaLoopStatus').innerText = data.message;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error during start media loop:", error);
|
||||
document.getElementById('mediaLoopStatus').innerText = "Error during start media loop.";
|
||||
});
|
||||
}
|
||||
|
||||
function stopMediaLoop() {
|
||||
fetch('../stop_media_loop', {
|
||||
method: 'POST'
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
document.getElementById('mediaLoopStatus').innerText = data.message;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error during stop media loop:", error);
|
||||
document.getElementById('mediaLoopStatus').innerText = "Error during stop media loop.";
|
||||
});
|
||||
}
|
||||
|
||||
function startWebGallery() {
|
||||
const autoStart = document.getElementById('autoStart').checked;
|
||||
const url = document.getElementById('galleryURL').value
|
||||
fetch('../start_web_gallery', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ url: url, autoStart: autoStart })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
document.getElementById('webGalleryStatus').innerText = data.message;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error during start web gallery:", error);
|
||||
document.getElementById('webGalleryStatus').innerText = "Error during start web gallery.";
|
||||
});
|
||||
}
|
||||
|
||||
function stopWebGallery() {
|
||||
fetch('../stop_web_gallery', {
|
||||
method: 'POST'
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
document.getElementById('webGalleryStatus').innerText = data.message;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error during stop web gallery:", error);
|
||||
document.getElementById('webGalleryStatus').innerText = "Error during stop web gallery.";
|
||||
});
|
||||
}
|
||||
|
||||
function clearURL() {
|
||||
document.getElementById('galleryURL').value = '';
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', loadLastUsedData);
|
||||
|
||||
// Call the function to load media sources when the page loads
|
||||
window.onload = loadMediaSources;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
307
templates/internet.html
Normal file
307
templates/internet.html
Normal file
@ -0,0 +1,307 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>WiFi Configuration</title>
|
||||
<link rel="icon" type="image/x-icon" href="/static/images/favicon.ico">
|
||||
<link rel="stylesheet" href="/static/css/styles.css">
|
||||
<link rel="stylesheet" href="/static/fontawesome/css/all.min.css">
|
||||
<style>
|
||||
h1 {
|
||||
margin-top: 30px;
|
||||
font-size: 36px;
|
||||
color: #333;
|
||||
}
|
||||
.button-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.btn {
|
||||
padding: 10px 20px;
|
||||
font-size: 1.2em;
|
||||
cursor: pointer;
|
||||
background-color: blue;
|
||||
color: white;
|
||||
width: 150px;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
.btn:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
.small-btn {
|
||||
width: 100px;
|
||||
padding: 5px 10px;
|
||||
font-size: 0.8em;
|
||||
background-color: darkslateblue;
|
||||
}
|
||||
.small-btn-container {
|
||||
margin-left: auto;
|
||||
}
|
||||
.scan-container {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.scan-container .btn {
|
||||
background-color: #28a745;
|
||||
}
|
||||
.scan-container .btn:hover {
|
||||
background-color: #218838;
|
||||
}
|
||||
.connect-container {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.connect-container .btn {
|
||||
padding: 5px 15px;
|
||||
border-radius: 5px;
|
||||
background-color: #ffc107;
|
||||
}
|
||||
.connect-container .btn:hover {
|
||||
background-color: #e0a800;
|
||||
}
|
||||
.network-list {
|
||||
margin-top: 20px;
|
||||
width: 100%;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #ccc;
|
||||
background-color: white;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.network-list table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.network-list th, .network-list td {
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #ddd;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.network-list th {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
.network-list tr.selected {
|
||||
background-color: #d1e7dd;
|
||||
}
|
||||
.status {
|
||||
margin-top: 20px;
|
||||
font-size: 18px;
|
||||
color: #555;
|
||||
}
|
||||
.home-btn {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
padding: 10px 20px;
|
||||
background-color: #6c757d;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.home-btn:hover {
|
||||
background-color: #5a6268;
|
||||
}
|
||||
.placeholder-img {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
.placeholder-img img {
|
||||
top: 20px;
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
}
|
||||
.header-img {
|
||||
margin-top: 20px; /* Adjust the margin as needed */
|
||||
margin-bottom: 30px;
|
||||
width: auto;
|
||||
height: 80px; /* Adjust the height as needed */
|
||||
position: absolute;
|
||||
left: 30px;
|
||||
top: 60px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="navbar"></div>
|
||||
<script>
|
||||
fetch('/static/html/nav.html')
|
||||
.then(response => response.text())
|
||||
.then(data => {
|
||||
document.getElementById('navbar').innerHTML = data;
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="content-wrapper">
|
||||
<div class="content">
|
||||
<h1>WiFi Internet Access</h1>
|
||||
<img src="/static/images/internet_icon.png" alt="internet" class="header-img">
|
||||
<label id="label-status">Status:</label>
|
||||
<div class="button-container">
|
||||
<button class="btn" id="scanButton" onclick="scanWifi()">Scan</button>
|
||||
<div class="small-btn-container">
|
||||
<button class="btn small-btn" id="forgetButton" onclick="checkForgetNetworks()">Forget all</button>
|
||||
<button class="btn small-btn" id="testButton" onclick="checkInternetAccess()">Test Internet</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="scan-container">
|
||||
<div id="scanStatus" class="status"></div>
|
||||
</div>
|
||||
<div class="network-list">
|
||||
<table id="networksTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>SSID</th>
|
||||
<th>Freq</th>
|
||||
<th>Signal</th>
|
||||
<th>Bssid</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- List of networks will be appended here -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="connect-container">
|
||||
<button class="btn" id="connectToNetworkButton"onclick="connectToNetwork()">Connect</button>
|
||||
</div>
|
||||
<div class="status" id="connectionStatus"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.onload = function() { OnPageLoad(); };
|
||||
|
||||
function scanWifi() {
|
||||
console.log("Starting WiFi scan...");
|
||||
document.getElementById('connectionStatus').innerText = ""
|
||||
document.getElementById('scanStatus').innerText = "Scanning for networks...";
|
||||
fetch('/wifi_scan')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log("Scan complete. Data received:", data);
|
||||
document.getElementById('scanStatus').innerText = "Scan complete.";
|
||||
let tableBody = document.getElementById('networksTable').getElementsByTagName('tbody')[0];
|
||||
tableBody.innerHTML = '';
|
||||
data.networks.forEach(network => {
|
||||
let row = tableBody.insertRow();
|
||||
let cell1 = row.insertCell(0);
|
||||
let cell2 = row.insertCell(1);
|
||||
let cell3 = row.insertCell(2);
|
||||
let cell4 = row.insertCell(3);
|
||||
cell1.textContent = network.ssid || '';
|
||||
cell2.textContent = network.Freq || '';
|
||||
cell3.textContent = network.signal || '';
|
||||
cell4.textContent = network.bssid || '';
|
||||
row.addEventListener('click', function() {
|
||||
const rows = document.querySelectorAll('#networksTable tbody tr');
|
||||
rows.forEach(r => r.classList.remove('selected'));
|
||||
row.classList.add('selected');
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error during scan:", error);
|
||||
document.getElementById('scanStatus').innerText = "Error during scan.";
|
||||
});
|
||||
}
|
||||
|
||||
function connectToNetwork() {
|
||||
console.log("Attempting to connect to network...");
|
||||
const table = document.getElementById('networksTable');
|
||||
const selectedRow = table.querySelector('tbody tr.selected');
|
||||
if (!selectedRow) {
|
||||
document.getElementById('connectionStatus').innerText = "Please select a network to connect to.";
|
||||
return;
|
||||
}
|
||||
const ssid = selectedRow.cells[0].textContent;
|
||||
const bssid = selectedRow.cells[3].textContent;
|
||||
const password = prompt("Enter the WiFi password for " + ssid + ":");
|
||||
if (!password) {
|
||||
document.getElementById('connectionStatus').innerText = "Connection cancelled.";
|
||||
return;
|
||||
}
|
||||
document.getElementById('connectionStatus').innerText = "Please wait...";
|
||||
document.getElementById('connectToNetworkButton').disabled = true;
|
||||
document.getElementById('scanButton').disabled = true;
|
||||
document.getElementById('testButton').disabled = true;
|
||||
document.getElementById('forgetButton').disabled = true;
|
||||
fetch('/wifi_connect', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ ssid: ssid, bssid: bssid, password: password })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log("Connection attempt result:", data);
|
||||
document.getElementById('connectionStatus').innerText = data.message;
|
||||
checkWifiStatus();
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error during connection attempt:", error);
|
||||
document.getElementById('connectionStatus').innerText = "Error during connection attempt.";
|
||||
})
|
||||
.finally(() => {
|
||||
// Re-enable buttons after the connection attempt
|
||||
document.getElementById('connectToNetworkButton').disabled = false;
|
||||
document.getElementById('scanButton').disabled = false;
|
||||
document.getElementById('testButton').disabled = false;
|
||||
document.getElementById('forgetButton').disabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
function checkInternetAccess() {
|
||||
fetch('/wifi_test')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const statusMessage = data.success ? "Internet Access Ok" : "No Internet Access";
|
||||
alert(statusMessage); // Display message in a popup
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error checking internet access:", error);
|
||||
alert("Error checking internet access."); // Display error in a popup
|
||||
});
|
||||
}
|
||||
|
||||
function checkForgetNetworks() {
|
||||
fetch('/wifi_forget')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const statusMessage = data.success ? "All networks forgotten" : "Nothing happened";
|
||||
alert(statusMessage); // Display message in a popup
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error forgetting networks:", error);
|
||||
alert("Error forgetting networks."); // Display error in a popup
|
||||
});
|
||||
}
|
||||
|
||||
function checkWifiStatus() {
|
||||
fetch('/wifi_status')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log("Data received:", data);
|
||||
document.getElementById('label-status').innerText = "Status: " + data.msg;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error getting wifi status:", error);
|
||||
document.getElementById('label-status').innerText = "Status: ...";
|
||||
});
|
||||
}
|
||||
|
||||
function OnPageLoad(){
|
||||
checkWifiStatus();
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
234
templates/wifi.html
Normal file
234
templates/wifi.html
Normal file
@ -0,0 +1,234 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>WiFi Configuration</title>
|
||||
<link rel="icon" type="image/x-icon" href="/static/images/favicon.ico">
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
min-height: 50vh;
|
||||
margin: 0;
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
h1 {
|
||||
margin-top: 30px;
|
||||
font-size: 36px;
|
||||
color: #333;
|
||||
}
|
||||
.button-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.button-container .btn {
|
||||
padding: 10px 20px;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
}
|
||||
.button-container .btn:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
.scan-container {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.scan-container .btn {
|
||||
background-color: #28a745;
|
||||
}
|
||||
.scan-container .btn:hover {
|
||||
background-color: #218838;
|
||||
}
|
||||
.connect-container {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.connect-container .btn {
|
||||
background-color: #ffc107;
|
||||
}
|
||||
.connect-container .btn:hover {
|
||||
background-color: #e0a800;
|
||||
}
|
||||
.network-list {
|
||||
margin-top: 20px;
|
||||
width: 80%;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #ccc;
|
||||
background-color: white;
|
||||
}
|
||||
.network-list table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: auto;
|
||||
}
|
||||
.network-list th, .network-list td {
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #ddd;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.network-list th {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
.network-list tr.selected {
|
||||
background-color: #d1e7dd;
|
||||
}
|
||||
.status {
|
||||
margin-top: 20px;
|
||||
font-size: 18px;
|
||||
color: #555;
|
||||
}
|
||||
.home-btn {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
padding: 10px 20px;
|
||||
background-color: #6c757d;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.home-btn:hover {
|
||||
background-color: #5a6268;
|
||||
}
|
||||
.placeholder-img {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
.placeholder-img img {
|
||||
top: 20px;
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a href="/" class="home-btn">Home</a>
|
||||
<div class="placeholder-img">
|
||||
<img src="/static/images/atalogo.png">
|
||||
</div>
|
||||
<h1>WiFi Connection</h1>
|
||||
<div class="button-container">
|
||||
<button class="btn" onclick="scanWifi()">Scan for Networks</button>
|
||||
<button class="btn" onclick="cancelScan()">Cancel</button>
|
||||
</div>
|
||||
<div class="scan-container">
|
||||
<div id="scanStatus" class="status"></div>
|
||||
</div>
|
||||
<div class="network-list">
|
||||
<table id="networksTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>SSID</th>
|
||||
<th>Freq</th>
|
||||
<th>Signal</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- List of networks will be appended here -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="connect-container">
|
||||
<button class="btn" onclick="connectToNetwork()">Connect</button>
|
||||
</div>
|
||||
<div class="status" id="connectionStatus"></div>
|
||||
<script>
|
||||
function scanWifi() {
|
||||
console.log("Starting WiFi scan...");
|
||||
document.getElementById('scanStatus').innerText = "Scanning for networks...";
|
||||
fetch('/scan_wifi')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log("Scan complete. Data received:", data);
|
||||
document.getElementById('scanStatus').innerText = "Scan complete.";
|
||||
let tableBody = document.getElementById('networksTable').getElementsByTagName('tbody')[0];
|
||||
tableBody.innerHTML = '';
|
||||
data.networks.forEach(network => {
|
||||
let row = tableBody.insertRow();
|
||||
let cell1 = row.insertCell(0);
|
||||
let cell2 = row.insertCell(1);
|
||||
let cell3 = row.insertCell(2);
|
||||
cell1.textContent = network.ssid;
|
||||
cell2.textContent = network.Freq;
|
||||
cell3.textContent = network.signal;
|
||||
row.addEventListener('click', function() {
|
||||
const rows = document.querySelectorAll('#networksTable tbody tr');
|
||||
rows.forEach(r => r.classList.remove('selected'));
|
||||
row.classList.add('selected');
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error during scan:", error);
|
||||
document.getElementById('scanStatus').innerText = "Error during scan.";
|
||||
});
|
||||
}
|
||||
|
||||
function cancelScan() {
|
||||
console.log("Cancelling scan...");
|
||||
document.getElementById('scanStatus').innerText = "Scan cancelled.";
|
||||
}
|
||||
|
||||
function connectToNetwork() {
|
||||
console.log("Attempting to connect to network...");
|
||||
const table = document.getElementById('networksTable');
|
||||
const selectedRow = table.querySelector('tbody tr.selected');
|
||||
if (!selectedRow) {
|
||||
document.getElementById('connectionStatus').innerText = "Please select a network to connect to.";
|
||||
return;
|
||||
}
|
||||
const ssid = selectedRow.cells[0].textContent;
|
||||
const password = prompt("Enter the WiFi password for " + ssid + ":");
|
||||
if (!password) {
|
||||
document.getElementById('connectionStatus').innerText = "Connection cancelled.";
|
||||
return;
|
||||
}
|
||||
fetch('/connect_wifi', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ ssid: ssid, password: password })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log("Connection attempt result:", data);
|
||||
document.getElementById('connectionStatus').innerText = data.message;
|
||||
if (data.success) {
|
||||
checkInternetAccess();
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error during connection attempt:", error);
|
||||
document.getElementById('connectionStatus').innerText = "Error during connection attempt.";
|
||||
});
|
||||
}
|
||||
|
||||
function checkInternetAccess() {
|
||||
fetch('/check_internet_access')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const statusMessage = data.success ? "Internet Access Ok" : "No Internet Access";
|
||||
document.getElementById('connectionStatus').innerText = statusMessage;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error checking internet access:", error);
|
||||
document.getElementById('connectionStatus').innerText = "Error checking internet access.";
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
20
update_atadash.sh
Normal file
20
update_atadash.sh
Normal file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
source /home/orangepi/atadash/.venv/bin/activate
|
||||
|
||||
# Stop the services
|
||||
echo "atadash stopping..."
|
||||
sudo systemctl stop atadash
|
||||
echo ""
|
||||
|
||||
# Use rsync to copy files if they are different
|
||||
rsync -avv --progress /home/orangepi/atadash_master/static/ /home/orangepi/atadash/static/
|
||||
rsync -avv --progress /home/orangepi/atadash_master/templates/ /home/orangepi/atadash/templates/
|
||||
rsync -avv --progress /home/orangepi/atadash_master/data/ /home/orangepi/atadash/data/
|
||||
|
||||
# Use pyarmor to protect Python scripts in the printio directory
|
||||
pyarmor gen -O /home/orangepi/atadash/src/ /home/orangepi/atadash_master/src/*.py
|
||||
|
||||
# Start the services back up
|
||||
echo ""
|
||||
sudo systemctl start atadash
|
||||
echo "atadash restarted..."
|
||||
Loading…
x
Reference in New Issue
Block a user