From 8c2214fc09f225b377d3d2b1398ff64a8bd54bd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Thu, 29 Jan 2015 16:39:09 +0100 Subject: [PATCH] Ordering of injected templates decoupled from template content Internal templates get handled the same way as those from plugins. Plugins may also in theory now replace existing internal templates, however for that to not cause any errors on the client side due to missing expected elements that will for now stay an undocumented feature. --- src/octoprint/server/__init__.py | 157 +++++++++++------- .../templates/dialogs/settings.jinja2 | 12 +- src/octoprint/templates/index.jinja2 | 15 +- 3 files changed, 116 insertions(+), 68 deletions(-) diff --git a/src/octoprint/server/__init__.py b/src/octoprint/server/__init__.py index 0f92799c..d294dc2d 100644 --- a/src/octoprint/server/__init__.py +++ b/src/octoprint/server/__init__.py @@ -115,6 +115,64 @@ def index(): for name, implementation in asset_plugins.items(): asset_plugin_urls[name] = implementation.get_assets() + templates = dict( + navbar=dict(order=[], entries=dict()), + sidebar=dict(order=[], entries=dict()), + tab=dict(order=[], entries=dict()), + settings=dict(order=[], entries=dict()), + generic=dict(order=[], entries=dict()) + ) + + #~~ navbar + + templates["navbar"]["entries"] = dict( + settings=dict(template="navbar/settings.jinja2", _div="navbar_settings", styles=["display: none"], data_bind="visible: loginState.isAdmin", custom_bindings=False), + systemmenu=dict(template="navbar/systemmenu.jinja2", _div="navbar_systemmenu", styles=["display: none"], classes=["dropdown"], data_bind="visible: loginState.isAdmin", custom_bindings=False), + login=dict(template="navbar/login.jinja2", _div="navbar_login", classes=["dropdown"], custom_bindings=False) + ) + + #~~ sidebar + + templates["sidebar"]["entries"]= dict( + connection=(gettext("Connection"), dict(template="sidebar/connection.jinja2", _div="connection", icon="signal", styles_wrapper=["display: none"], data_bind="visible: loginState.isAdmin")), + state=(gettext("State"), dict(template="sidebar/state.jinja2", _div="state", icon="info-sign")), + files=(gettext("Files"), dict(template="sidebar/files.jinja2", _div="files", icon="list", classes_content=["overflow_visible"], header_addon="sidebar/files_header.jinja2")) + ) + + #~~ tabs + + templates["tab"]["entries"] = dict( + temperature=(gettext("Temperature"), dict(template="tabs/temperature.jinja2", _div="temp")), + control=(gettext("Control"), dict(template="tabs/control.jinja2", _div="control")), + gcodeviewer=(gettext("GCode Viewer"), dict(template="tabs/gcodeviewer.jinja2", _div="gcode")), + terminal=(gettext("Terminal"), dict(template="tabs/terminal.jinja2", _div="term")), + timelapse=(gettext("Timelapse"), dict(template="tabs/timelapse.jinja2", _div="timelapse")) + ) + + #~~ settings dialog + + templates["settings"]["entries"] = dict( + section_printer=(gettext("Printer"), None), + + serial=(gettext("Serial Connection"), dict(template="dialogs/settings/serialconnection.jinja2", _div="settings_serialConnection", custom_bindings=False)), + printerprofiles=(gettext("Printer Profiles"), dict(template="dialogs/settings/printerprofiles.jinja2", _div="settings_printerProfiles", custom_bindings=False)), + temperatures=(gettext("Temperatures"), dict(template="dialogs/settings/temperatures.jinja2", _div="settings_temperature", custom_bindings=False)), + terminalfilters=(gettext("Terminal Filters"), dict(template="dialogs/settings/terminalfilters.jinja2", _div="settings_terminalFilters", custom_bindings=False)), + + section_features=(gettext("Features"), None), + + features=(gettext("Features"), dict(template="dialogs/settings/features.jinja2", _div="settings_features", custom_bindings=False)), + webcam=(gettext("Webcam"), dict(template="dialogs/settings/webcam.jinja2", _div="settings_webcam", custom_bindings=False)), + accesscontrol=(gettext("Access Control"), dict(template="dialogs/settings/accesscontrol.jinja2", _div="settings_users", custom_bindings=False)), + api=(gettext("API"), dict(template="dialogs/settings/api.jinja2", _div="settings_api", custom_bindings=False)), + + section_octoprint=(gettext("OctoPrint"), None), + + folders=(gettext("Folders"), dict(template="dialogs/settings/folders.jinja2", _div="settings_folders", custom_bindings=False)), + appearance=(gettext("Appearance"), dict(template="dialogs/settings/appearance.jinja2", _div="settings_appearance", custom_bindings=False)), + logs=(gettext("Logs"), dict(template="dialogs/settings/logs.jinja2", _div="settings_logs")), + ) + #~~ extract data from template plugins template_plugins = pluginManager.get_implementations(octoprint.plugin.TemplatePlugin) @@ -129,11 +187,6 @@ def index(): ) plugin_vars = dict() - plugin_includes_navbar = [] - plugin_includes_sidebar = [] - plugin_includes_tabs = [] - plugin_includes_settings = [] - plugin_includes_generic = [] plugin_names = template_plugins.keys() for name, implementation in template_plugins.items(): vars = implementation.get_template_vars() @@ -149,59 +202,51 @@ def index(): includes = _process_template_configs(name, implementation, configs, rules) - plugin_includes_navbar += includes["navbar"] - plugin_includes_sidebar += includes["sidebar"] - plugin_includes_tabs += includes["tab"] - plugin_includes_settings += includes["settings"] - plugin_includes_generic += includes["generic"] + for t in ("navbar", "sidebar", "tab", "settings", "generic"): + for include in includes[t]: + if t == "navbar" or t == "generic": + data = include + else: + data = include[1] - #~~ navbar + key = "plugin_" + name + data["suffix"] if "suffix" in data else "" + if "replaces" in data: + key = data["replaces"] + templates[t]["entries"][key] = include - navbar_entries = plugin_includes_navbar + [ - dict(template="navbar/settings.jinja2", _div="navbar_settings", styles=["display: none"], data_bind="visible: loginState.isAdmin", custom_bindings=False), - dict(template="navbar/systemmenu.jinja2", _div="navbar_systemmenu", styles=["display: none"], classes=["dropdown"], data_bind="visible: loginState.isAdmin", custom_bindings=False), - dict(template="navbar/login.jinja2", _div="navbar_login", classes=["dropdown"], custom_bindings=False) + #~~ order internal templates and plugins + + templates["navbar"]["order"] = ["settings", "systemmenu", "login"] + templates["sidebar"]["order"] = ["connection", "state", "files"] + templates["tab"]["order"] = ["temperature", "control", "gcodeviewer", "terminal", "timelapse"] + templates["settings"]["order"] = [ + "section_printer", "serial", "printerprofiles", "temperatures", "terminalfilters", + "section_features", "features", "webcam", "accesscontrol", "api", + "section_octoprint", "folders", "appearance", "logs" ] - #~~ sidebar + # make sure that + # 1) we only have keys in our ordered list that we have entries for and + # 2) we have all entries located somewhere within the order - sidebar_entries = [ - (gettext("Connection"), dict(template="sidebar/connection.jinja2", _div="connection", icon="signal", styles_wrapper=["display: none"], data_bind="visible: loginState.isAdmin")), - (gettext("State"), dict(template="sidebar/state.jinja2", _div="state", icon="info-sign")), - (gettext("Files"), dict(template="sidebar/files.jinja2", _div="files", icon="list", classes_content=["overflow_visible"], header_addon="sidebar/files_header.jinja2")) - ] + plugin_includes_sidebar + for t in ("navbar", "sidebar", "tab", "settings", "generic"): + templates[t]["order"] = [x for x in templates[t]["order"] if x in templates[t]["entries"]] + all_ordered = set(templates[t]["order"]) - #~~ tabs + missing_in_order = set(templates[t]["entries"].keys()).difference(all_ordered) + if len(missing_in_order) == 0: + continue - tab_entries = [ - (gettext("Temperature"), dict(template="tabs/temperature.jinja2", _div="temp")), - (gettext("Control"), dict(template="tabs/control.jinja2", _div="control")), - (gettext("GCode Viewer"), dict(template="tabs/gcodeviewer.jinja2", _div="gcode")), - (gettext("Terminal"), dict(template="tabs/terminal.jinja2", _div="term")), - (gettext("Timelapse"), dict(template="tabs/timelapse.jinja2", _div="timelapse")) - ] + plugin_includes_tabs - - #~~ settings dialog - - settings_entries = [ - (gettext("Printer"), None), - (gettext("Serial Connection"), dict(template="dialogs/settings/serialconnection.jinja2", _div="settings_serialConnection", custom_bindings=False)), - (gettext("Printer Profiles"), dict(template="dialogs/settings/printerprofiles.jinja2", _div="settings_printerProfiles", custom_bindings=False)), - (gettext("Temperatures"), dict(template="dialogs/settings/temperatures.jinja2", _div="settings_temperature", custom_bindings=False)), - (gettext("Terminal Filters"), dict(template="dialogs/settings/terminalfilters.jinja2", _div="settings_terminalFilters", custom_bindings=False)), - (gettext("Features"), None), - (gettext("Features"), dict(template="dialogs/settings/features.jinja2", _div="settings_features", custom_bindings=False)), - (gettext("Webcam"), dict(template="dialogs/settings/webcam.jinja2", _div="settings_webcam", custom_bindings=False)), - (gettext("Access Control"), dict(template="dialogs/settings/accesscontrol.jinja2", _div="settings_users", custom_bindings=False)), - (gettext("API"), dict(template="dialogs/settings/api.jinja2", _div="settings_api", custom_bindings=False)), - (gettext("OctoPrint"), None), - (gettext("Folders"), dict(template="dialogs/settings/folders.jinja2", _div="settings_folders", custom_bindings=False)), - (gettext("Appearance"), dict(template="dialogs/settings/appearance.jinja2", _div="settings_appearance", custom_bindings=False)), - (gettext("Logs"), dict(template="dialogs/settings/logs.jinja2", _div="settings_logs")) - ] - if len(plugin_includes_settings): - settings_entries.append((gettext("Plugins"), None)) - settings_entries.extend(sorted(plugin_includes_settings, key=lambda x: x[0])) + sorted_missing = list(missing_in_order) + if not t == "navbar" and not t == "generic": + sorted_missing = sorted(missing_in_order, key=lambda x: templates[t]["entries"][x][0]) + if t == "navbar": + templates[t]["order"] = sorted_missing + templates[t]["order"] + elif t == "sidebar" or t == "tab" or t == "generic": + templates[t]["order"] += sorted_missing + elif t == "settings": + templates[t]["entries"]["section_plugins"] = (gettext("Plugins"), None) + templates[t]["order"] += ["section_plugins"] + sorted_missing #~~ prepare full set of template vars for rendering @@ -221,11 +266,7 @@ def index(): gcodeMobileThreshold=settings().get(["gcodeViewer", "mobileSizeThreshold"]), gcodeThreshold=settings().get(["gcodeViewer", "sizeThreshold"]), uiApiKey=UI_API_KEY, - navbarEntries=navbar_entries, - sidebarEntries=sidebar_entries, - tabEntries=tab_entries, - settingsEntries=settings_entries, - genericEntries=plugin_includes_generic, + templates=templates, pluginNames=plugin_names, assetPlugins=asset_plugin_urls, ) @@ -299,9 +340,11 @@ def _process_template_config(name, implementation, rule, config=None, counter=1) data["_div"] = rule["div"](name) if "suffix" in data: data["_div"] += "_" + data["suffix"] - del data["suffix"] elif counter > 1: data["_div"] += "_%d" % counter + data["suffix"] = "_%d" % counter + else: + data["suffix"] = "" if not "template" in data: data["template"] = rule["template"](name) if not "name" in data: diff --git a/src/octoprint/templates/dialogs/settings.jinja2 b/src/octoprint/templates/dialogs/settings.jinja2 index c6ab24a9..2896745f 100644 --- a/src/octoprint/templates/dialogs/settings.jinja2 +++ b/src/octoprint/templates/dialogs/settings.jinja2 @@ -6,15 +6,15 @@