app: use Jinja2 to render the welcome landing page
Read the template using the "source_info" utility, which uses a zip-safe method to read a file. Signed-off-by: Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
parent
7520d0e7b1
commit
5a504243df
|
@ -22,7 +22,7 @@ from tornado.escape import url_unescape, url_escape
|
||||||
from tornado.routing import Rule, PathMatches, AnyMatches
|
from tornado.routing import Rule, PathMatches, AnyMatches
|
||||||
from tornado.http1connection import HTTP1Connection
|
from tornado.http1connection import HTTP1Connection
|
||||||
from tornado.log import access_log
|
from tornado.log import access_log
|
||||||
from .utils import ServerError
|
from .utils import ServerError, source_info
|
||||||
from .websockets import (
|
from .websockets import (
|
||||||
WebRequest,
|
WebRequest,
|
||||||
WebsocketManager,
|
WebsocketManager,
|
||||||
|
@ -57,6 +57,7 @@ if TYPE_CHECKING:
|
||||||
from .components.machine import Machine
|
from .components.machine import Machine
|
||||||
from io import BufferedReader
|
from io import BufferedReader
|
||||||
from .components.authorization import Authorization
|
from .components.authorization import Authorization
|
||||||
|
from .components.template import TemplateFactory, JinjaTemplate
|
||||||
MessageDelgate = Optional[tornado.httputil.HTTPMessageDelegate]
|
MessageDelgate = Optional[tornado.httputil.HTTPMessageDelegate]
|
||||||
AuthComp = Optional[Authorization]
|
AuthComp = Optional[Authorization]
|
||||||
APICallback = Callable[[WebRequest], Coroutine]
|
APICallback = Callable[[WebRequest], Coroutine]
|
||||||
|
@ -69,7 +70,6 @@ EXCLUDED_ARGS = ["_", "token", "access_token", "connection_id"]
|
||||||
AUTHORIZED_EXTS = [".png", ".jpg"]
|
AUTHORIZED_EXTS = [".png", ".jpg"]
|
||||||
DEFAULT_KLIPPY_LOG_PATH = "/tmp/klippy.log"
|
DEFAULT_KLIPPY_LOG_PATH = "/tmp/klippy.log"
|
||||||
ALL_TRANSPORTS = ["http", "websocket", "mqtt", "internal"]
|
ALL_TRANSPORTS = ["http", "websocket", "mqtt", "internal"]
|
||||||
ASSET_PATH = pathlib.Path(__file__).parent.joinpath("assets")
|
|
||||||
|
|
||||||
class MutableRouter(tornado.web.ReversibleRuleRouter):
|
class MutableRouter(tornado.web.ReversibleRuleRouter):
|
||||||
def __init__(self, application: MoonrakerApp) -> None:
|
def __init__(self, application: MoonrakerApp) -> None:
|
||||||
|
@ -173,6 +173,7 @@ class MoonrakerApp:
|
||||||
self.http_server: Optional[HTTPServer] = None
|
self.http_server: Optional[HTTPServer] = None
|
||||||
self.secure_server: Optional[HTTPServer] = None
|
self.secure_server: Optional[HTTPServer] = None
|
||||||
self.api_cache: Dict[str, APIDefinition] = {}
|
self.api_cache: Dict[str, APIDefinition] = {}
|
||||||
|
self.template_cache: Dict[str, JinjaTemplate] = {}
|
||||||
self.registered_base_handlers: List[str] = []
|
self.registered_base_handlers: List[str] = []
|
||||||
self.max_upload_size = config.getint('max_upload_size', 1024)
|
self.max_upload_size = config.getint('max_upload_size', 1024)
|
||||||
self.max_upload_size *= 1024 * 1024
|
self.max_upload_size *= 1024 * 1024
|
||||||
|
@ -304,9 +305,6 @@ class MoonrakerApp:
|
||||||
def get_server(self) -> Server:
|
def get_server(self) -> Server:
|
||||||
return self.server
|
return self.server
|
||||||
|
|
||||||
def get_asset_path(self) -> pathlib.Path:
|
|
||||||
return ASSET_PATH
|
|
||||||
|
|
||||||
def https_enabled(self) -> bool:
|
def https_enabled(self) -> bool:
|
||||||
return self.cert_path.exists() and self.key_path.exists()
|
return self.cert_path.exists() and self.key_path.exists()
|
||||||
|
|
||||||
|
@ -465,6 +463,20 @@ class MoonrakerApp:
|
||||||
self.api_cache[endpoint] = api_def
|
self.api_cache[endpoint] = api_def
|
||||||
return api_def
|
return api_def
|
||||||
|
|
||||||
|
async def load_template(self, asset_name: str) -> JinjaTemplate:
|
||||||
|
if asset_name in self.template_cache:
|
||||||
|
return self.template_cache[asset_name]
|
||||||
|
eventloop = self.server.get_event_loop()
|
||||||
|
asset = await eventloop.run_in_thread(
|
||||||
|
source_info.read_asset, asset_name
|
||||||
|
)
|
||||||
|
if asset is None:
|
||||||
|
raise tornado.web.HTTPError(404, "Asset Not Found")
|
||||||
|
template: TemplateFactory = self.server.lookup_component("template")
|
||||||
|
asset_tmpl = template.create_ui_template(asset)
|
||||||
|
self.template_cache[asset_name] = asset_tmpl
|
||||||
|
return asset_tmpl
|
||||||
|
|
||||||
class AuthorizedRequestHandler(tornado.web.RequestHandler):
|
class AuthorizedRequestHandler(tornado.web.RequestHandler):
|
||||||
def initialize(self) -> None:
|
def initialize(self) -> None:
|
||||||
self.server: Server = self.settings['server']
|
self.server: Server = self.settings['server']
|
||||||
|
@ -1084,7 +1096,7 @@ class WelcomeHandler(tornado.web.RequestHandler):
|
||||||
"service_name": svc_info.get("unit_name", "unknown"),
|
"service_name": svc_info.get("unit_name", "unknown"),
|
||||||
"hostname": self.server.get_host_info()["hostname"],
|
"hostname": self.server.get_host_info()["hostname"],
|
||||||
}
|
}
|
||||||
self.render("welcome.html", **context)
|
app: MoonrakerApp = self.server.lookup_component("application")
|
||||||
|
welcome_template = await app.load_template("welcome.html")
|
||||||
def get_template_path(self) -> Optional[str]:
|
ret = await welcome_template.render_async(context)
|
||||||
return str(ASSET_PATH)
|
self.finish(ret)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
# Assets Package Definition
|
|
@ -328,10 +328,10 @@
|
||||||
<div class="content">
|
<div class="content">
|
||||||
{% for item in summary %}
|
{% for item in summary %}
|
||||||
<article class="item">{{ item }}</article>
|
<article class="item">{{ item }}</article>
|
||||||
{% end %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
{% end %}
|
{% endif %}
|
||||||
{% if announcements %}
|
{% if announcements %}
|
||||||
<article class="card messages">
|
<article class="card messages">
|
||||||
<h1>Announcements</h1>
|
<h1>Announcements</h1>
|
||||||
|
@ -346,20 +346,20 @@
|
||||||
<script>
|
<script>
|
||||||
setClickable("{{ id }}");
|
setClickable("{{ id }}");
|
||||||
</script>
|
</script>
|
||||||
{% end %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
{% end %}
|
{% endif %}
|
||||||
{% if warnings %}
|
{% if warnings %}
|
||||||
<article class="card messages warning">
|
<article class="card messages warning">
|
||||||
<h1>Warnings</h1>
|
<h1>Warnings</h1>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
{% for warn in warnings %}
|
{% for warn in warnings %}
|
||||||
<article class="item">{{ warn }}</article>
|
<article class="item">{{ warn }}</article>
|
||||||
{% end %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
{% end %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div id="update_modal" class="modal">
|
<div id="update_modal" class="modal">
|
||||||
<div class="modal-card">
|
<div class="modal-card">
|
||||||
|
@ -410,7 +410,7 @@
|
||||||
const modal = document.getElementById("update_modal");
|
const modal = document.getElementById("update_modal");
|
||||||
{% if sudo_requested %}
|
{% if sudo_requested %}
|
||||||
modal.style.display = "block";
|
modal.style.display = "block";
|
||||||
{% end %}
|
{% endif %}
|
||||||
const main_form = document.getElementById("main_form")
|
const main_form = document.getElementById("main_form")
|
||||||
const status_item = document.getElementById("modal_status");
|
const status_item = document.getElementById("modal_status");
|
||||||
const status_div = document.getElementById("status_msg");
|
const status_div = document.getElementById("status_msg");
|
||||||
|
|
Loading…
Reference in New Issue