diff --git a/docs/configuration/config_yaml.rst b/docs/configuration/config_yaml.rst index 14116796..9efa5f47 100644 --- a/docs/configuration/config_yaml.rst +++ b/docs/configuration/config_yaml.rst @@ -11,6 +11,10 @@ settings. Note that many of these settings are available from the "Settings" menu in OctoPrint itself. +.. contents:: + +.. _sec-configuration-config_yaml-serial: + Serial ------ @@ -52,6 +56,8 @@ Use the following settings to configure the serial connection to the printer: additionalPorts: - /dev/myPrinterSymlink +.. _sec-configuration-config_yaml-server: + Server ------ @@ -95,6 +101,8 @@ Use the following settings to configure the server: `into OctoPrint's wiki `_ for a couple of examples on how to configure this. +.. _sec-configuration-config_yaml-webcam: + Webcam ------ @@ -133,6 +141,8 @@ Use the following settings to configure webcam support: options: interval: 2 +.. _sec-configuration-config_yaml-feature: + Feature ------- @@ -162,6 +172,8 @@ Use the following settings to enable or disable OctoPrint features: # Specifies whether support for SD printing and file management should be enabled sdSupport: true +.. _sec-configuration-config_yaml-folder: + Folder ------ @@ -194,6 +206,8 @@ Use the following settings to set custom paths for folders used by OctoPrint: # and/or sliced objects to print in the future. watched: /path/to/watched/folder +.. _sec-configuration-config_yaml-temperature: + Temperature ----------- @@ -210,21 +224,128 @@ Use the following settings to configure temperature profiles which will be displ extruder: 180 bed: 60 +.. _sec-configuration-config_yaml-appearance: + Appearance ---------- Use the following settings to tweak OctoPrint's appearance a bit to better distinguish multiple instances/printers -appearance: +appearance or to modify the order and presence of the various UI components: .. code-block:: yaml appearance: - # Use this to give your printer a name. It will be displayed in the title bar (as " [OctoPrint]") and in the - # navigation bar (as "OctoPrint: ") - name: My Printer Model + # Use this to give your printer a name. It will be displayed in the title bar + # (as " [OctoPrint]") and in the navigation bar (as "OctoPrint: ") + name: My Printer - # Use this to color the navigation bar. Supported colors are red, orange, yellow, green, blue, violet and default. - color: blue + # Use this to color the navigation bar. Supported colors are red, orange, + # yellow, green, blue, violet and default. + color: default + + # Makes the color of the navigation bar "transparent". In case your printer uses + # acrylic for its frame ;) + colorTransparent: false + + # Configures the order and availability of the UI components + components: + + # Defines the order of the components within their respective containers. + # + # If overridden by the user the resulting order for display will be calculated as + # follows: + # + # - first all components as defined by the user + # - then all enabled core components as define in the default order (see below) + # + # Components not contained within the default order (e.g. from plugins) will be either + # prepended or appended to that result, depending on component type. + # + # Note that a component is not included in the order as defined by the user will still + # be put into the container, according to the default order. To fully disable a + # component, you'll need to add it to the container's disabled list further below. + order: + + # order of navbar items + navbar: + - settings + - systemmenu + - login + + # order of sidebar items + sidebar: + - connection + - state + - files + + # order of tab items + tab: + - temperature + - control + - gcodeviewer + - terminal + - timelapse + + # order of settings, if settings plugins are registered gets extended internally by + # section_plugins and all settings plugins + settings + - section_printer + - serial + - printerprofiles + - temperatures + - terminalfilters + - gcodescripts + - section_features + - features + - webcam + - accesscontrol + - api + - section_octoprint + - folders + - appearance + - logs + + # order of user settings + usersettings: + - access + - interface + + # order of generic templates + generic: [] + + # Disabled components per container. If a component is included here it will not + # be included in OctoPrint's UI at all. Note that this might mean that critical + # functionality will not be available if no replacement is registered. + disabled: + navbar: [], + sidebar: [], + tab: [], + settings: [], + usersettings: [], + generic: [] + +.. note:: + + By modifying the ``components`` > ``order`` lists you may reorder OctoPrint's UI components as you like. You can also + inject Plugins at another than their default location in their respective container by adding the entry + ``plugin_`` where you want them to appear. + + Example: If you want the tab of the :ref:`Hello World Plugin ` to appear as the first tab + in OctoPrint, you'd need to redefine ``components`` > ``order`` > ``tab`` by including something like this in your + ``config.yaml``: + + .. code-block:: yaml + + appearance: + components: + order: + tab: + - plugin_helloworld + + OctoPrint will then turn this into the order ``plugin_helloworld``, ``temperature``, ``control``, ``gcodeviewer``, + ``terminal``, ``timelapse`` plus any other plugins. + +.. _sec-configuration-config_yaml-controls: Controls -------- @@ -249,6 +370,8 @@ OctoPrint. type: command command: M107 +.. _sec-configuration-config_yaml-system: + System ------ @@ -269,6 +392,8 @@ OctoPrint is running is allowed to do this without password entry: command: sudo shutdown -h now confirm: You are about to shutdown the system. +.. _sec-configuration-config_yaml-accesscontrol: + Access Control -------------- @@ -305,6 +430,8 @@ Use the following settings to enable access control: - 127.0.0.0/8 - 192.168.1.0/24 +.. _sec-configuration-config_yaml-events: + Events ------ @@ -326,6 +453,8 @@ Use the following settings to add shell/gcode commands to be executed on certain type: gcode enabled: False +.. _sec-configuration-config_yaml-terminalfilters: + Terminal Filters ---------------- @@ -343,6 +472,8 @@ Use `Javascript regular expressions `_. + +.. _sec-plugins-templates-navbar: + +Navbar +------ + +The right part of the navigation bar located at the top of the UI can be enriched with additional links. Note that +with the current implementation, plugins will always be located *to the left* of the existing links. + +The included template must be called ``_navbar.jinja2`` (e.g. ``myplugin_navbar.jinja2``) unless +overridden by the configuration supplied through :func:`get_template_configs`. + +The template will be already wrapped into the necessary structure, plugins just need to supply the pure content. The +wrapper structure will have all additional classes and styles applied as specified via the configuration supplied +through :func:`get_template_configs`. + +.. _sec-plugins-templates-sidebar: + +Sidebar +------- + +The left side bar containing Connection, State and Files sections can be enriched with additional sections. Note +that with the current implementations, plugins will always be located *beneath* the existing sections. + +The included template must be called ``_sidebar.jinja2`` (e.g. ``myplugin_sidebar.jinja2``) unless +overridden by the configuration supplied through :func:`get_template_configs`. + +The template will be already wrapped into the necessary structure, plugins just need to supply the pure content. The +wrapper divs for both the whole box as well as the content pane will have all additional classes and styles applied +as specified via the configuration supplied through :func:`get_template_configs`. + +.. _sec-plugins-templates-tabs: + +Tabs +---- + +The available tabs of the main part of the interface may be extended with additional tabs originating from within +plugins. Note that with the current implementation, plugins will always be located *to the right* of the existing +tabs. + +The included template must be called ``_tab.jinja2`` (e.g. ``myplugin_tab.jinja2``) unless +overridden by the configuration supplied through :func:`get_template_configs`. + +The template will be already wrapped into the necessary structure, plugins just need to supply the pure content. The +wrapper div and the link in the navigation will have the additional classes and styles applied as specified via the +configuration supplied through :func:`get_template_configs`. + +.. _sec-plugins-templates-settings: + +Settings +-------- + +Plugins may inject a dialog into the existing settings view. Note that with the current implementations, plugins +will always be listed beneath the "Plugins" header in the settings link list, ordered alphabetically after +their displayed name. + +The included template must be called ``_settings.jinja2`` (e.g. ``myplugin_settings.jinja2``) unless +overridden by the configuration supplied through :func:`get_template_configs`. + +The template will be already wrapped into the necessary structure, plugins just need to supply the pure content. The +wrapper div and the link in the navigation will have the additional classes and styles applied as defined via the +supplied configuration supplied through :func:`get_template_configs`. + +.. _sec-plugins-templates-generic: + +Generic +------- + +Plugins may also inject arbitrary templates into the page of the web interface itself, e.g. in order to +add overlays or dialogs to be called from within the plugin's javascript code. + +.. _sec-plugins-templates-replacement: + +Replacing existing components +----------------------------- diff --git a/src/octoprint/plugin/types.py b/src/octoprint/plugin/types.py index fdaff494..2f38879d 100644 --- a/src/octoprint/plugin/types.py +++ b/src/octoprint/plugin/types.py @@ -232,218 +232,134 @@ class TemplatePlugin(OctoPrintPlugin): Template injection types in the settings - You can find an example for a simple plugin which injects navbar, sidebar, tab and settings content into the interface in - `the "helloworld" plugin in OctoPrint's collection of plugin examples `_. + You can find an example for a simple plugin which injects navbar, tab and settings content into the interface in + the "helloworld" plugin in OctoPrint's :ref:`Plugin Tutorial `. + + Plugins may replace existing components, see the ``replaces`` keyword in the template configurations returned by + :meth:`.get_template_configs` below. Note that if a plugin replaces a core component, it is the plugin's + responsibility to ensure that all core functionality is still maintained. """ def get_template_configs(self): """ Allows configuration of injected navbar, sidebar, tab and settings templates. Should be a list containing one - configuration object per template to inject. Each configuration object is represented by a dictionary with a mandatory key - ``type`` encoding the template type the configuration is targeting. Possible values here are ``navbar``, ``sidebar``, - ``tab``, ``settings`` and ``generic``. + configuration object per template to inject. Each configuration object is represented by a dictionary which + may contain the following keys: + + .. list-table:: + :widths: 5 95 + + * - type + - The template type the configuration is targeting. Possible values here are ``navbar``, ``sidebar``, + ``tab``, ``settings`` and ``generic``. Mandatory. + * - name + - The name of the component, if not set the name of the plugin will be used. The name will be visible at + a location depending on the ``type``: + + * ``navbar``: unused + * ``sidebar``: sidebar heading + * ``tab``: tab heading + * ``settings``: settings link + * ``generic``: unused + + * - template + - Name of the template to inject, default value depends on the ``type``: + + * ``navbar``: ``_navbar.jinja2`` + * ``sidebar``: ``_sidebar.jinja2`` + * ``tab``: ``_tab.jinja2`` + * ``settings``: ``_settings.jinja2`` + * ``generic``: ``.jinja2`` + + * - suffix + - Suffix to attach to the component identifier and the div identifier of the injected template. Will be + ``_`` if not provided and not the first template of the type, with ``index`` counting from 1 and + increasing for each template of the same type. + + Example: If your plugin with identifier ``myplugin`` defines two tab components like this: + + .. code-block:: python + + return [ + dict(type="tab", template="myplugin_first_tab.jinja2"), + dict(type="tab", template="myplugin_second_tab.jinja2") + ] + + then the first tab will have the component identifier ``plugin_myplugin`` and the second one will have + the component identifier ``plugin_myplugin_2`` (the generated divs will be ``tab_plugin_myplugin`` and + ``tab_plugin_myplugin_2`` accordingly). Notice that the first tab is *not* called ``plugin_myplugin_1`` -- + as stated above while the ``index`` used as default suffix starts counting at 1, it will not be applied + for the first component of a given type. + + If on the other hand your plugin's definition looks like this: + + .. code-block:: python + + return [ + dict(type="tab", template="myplugin_first_tab_jinja2", suffix="_1st"), + dict(type="tab", template="myplugin_second_tab_jinja2", suffix="_2nd") + ] + + then the generated component identifier will be ``plugin_myplugin_1st`` and ``plugin_myplugin_2nd`` + (and the divs will be ``tab_plugin_myplugin_1st`` and ``tab_plugin_myplugin_2nd``). + + * - div + - Id for the div containing the component. If not provided, defaults to ``_plugin_`` plus + the ``suffix`` if provided or required. + * - replaces + - Id of the component this one replaces, might be either one of the core components or a component + provided by another plugin. A list of the core component identifiers can be found + :ref:`in the configuration documentation `. The identifiers of + other plugin components always follow the format described above. + * - custom_bindings + - A boolean value indicating whether the default view model should be bound to the component (``false``) + or if a custom binding will be used by the plugin (``true``, default). + * - data_bind + - Additional knockout data bindings to apply to the component, can be used to add further behaviour to + the container based on internal state if necessary. + * - classes + - Additional classes to apply to the component, as a list of individual classes + (e.g. ``classes=["myclass", "myotherclass"]``) which will be joined into the correct format by the template engine. + * - styles + - Additional CSS styles to apply to the component, as a list of individual declarations + (e.g. ``styles=["color: red", "display: block"]``) which will be joined into the correct format by the template + engine. Further keys to be included in the dictionary depend on the type: - ``navbar`` type - .. figure:: ../images/template-plugin-type-navbar.png - :align: center - :alt: Structure of navbar plugins - - Structure of navbar plugins - - Configures a navbar component to inject. The following keys are supported: - - .. list-table:: - :widths: 5 95 - - * - template - - Name of the template to inject, defaults to ``_navbar.jinja2``. - * - suffix - - Suffix to attach to the element ID of the injected template, will be ``_`` if not provided and not - the first template of the type, with ``index`` counting from 1 and increasing for each template of the same - type. - * - div - - Id for the div containing the component. If not provided, defaults to ``plugin_`` plus - the suffix if provided or required. - * - replaces - - Id of navbar component this one replaces, might be either one of the core components or a component - provided by another plugin. See :ref:`this section ` for more on replacing template components. - * - custom_bindings - - A boolean value indicating whether the default view model should be bound to the navbar entry (``false``) - or if a custom binding will be used by the plugin (``true``, default). - * - data_bind - - Additional knockout data bindings to apply to the navbar entry, can be used to add further behaviour to - the container based on internal state if necessary. - * - classes - - Additional classes to apply to the navbar entry, as a list of individual classes - (e.g. ``classes=["myclass", "myotherclass"]``) which will be joined into the correct format by the template engine. - * - styles - - Additional CSS styles to apply to the navbar entry, as a list of individual declarations - (e.g. ``styles=["color: red", "display: block"]``) which will be joined into the correct format by the template - engine. - ``sidebar`` type - .. figure:: ../images/template-plugin-type-sidebar.png - :align: center - :alt: Structure of sidebar plugins - - Structure of sidebar plugins - - Configures a sidebar component to inject. The following keys are supported: .. list-table:: :widths: 5 95 - * - name - - The name of the sidebar entry, if not set the name of the plugin will be used. * - icon - Icon to use for the sidebar header, should be the name of a Font Awesome icon without the leading ``icon-`` part. - * - template - - Name of the template to inject, defaults to ``_sidebar.jinja2``. * - template_header - Additional template to include in the head section of the sidebar item. For an example of this, see the additional options included in the "Files" section. - * - suffix - - Suffix to attach to the element ID of the injected template, will be ``_`` if not provided and not - the first template of the type, with ``index`` counting from 1 and increasing for each template of the same - type. - * - div - - Id for the div containing the component. If not provided, defaults to ``plugin_`` plus - the suffix if provided or required. - * - replaces - - Id of sidebar component this one replaces, might be either one of the core components or a component - provided by another plugin. See :ref:`this section ` for more on replacing template components. - * - custom_bindings - - A boolean value indicating whether the default view model should be bound to the sidebar container (``false``) - or if a custom binding will be used by the plugin (``true``, default). - * - data_bind - - Additional knockout data bindings to apply to the template container, can be used to add further behaviour to - the container based on internal state if necessary. - * - classes - - Additional classes to apply to both the wrapper around the sidebar box as well as the content pane itself, as a - list of individual classes (e.g. ``classes=["myclass", "myotherclass"]``) which will be joined into the correct - format by the template engine. * - classes_wrapper - Like ``classes`` but only applied to the whole wrapper around the sidebar box. * - classes_content - Like ``classes`` but only applied to the content pane itself. - * - styles - - Additional CSS styles to apply to both the wrapper around the sidebar box as well as the content pane itself, - as a list of individual declarations (e.g. ``styles=["color: red", "display: block"]``) which will be joined - into the correct format by the template engine. * - styles_wrapper - Like ``styles`` but only applied to the whole wrapper around the sidebar box. * - styles_content - Like ``styles`` but only applied to the content pane itself - ``tab`` type - .. figure:: ../images/template-plugin-type-tab.png - :align: center - :alt: Structure of tab plugins - - Structure of tab plugins - - Configures a tab component to inject. The value must be a dictionary, supported values are the following: + ``tab`` type and ``settings`` type .. list-table:: :widths: 5 95 - * - name - - The name under which to include the tab, if not set the name of the plugin will be used. - * - template - - Name of the template to inject, defaults to ``_tab.jinja2``. - * - suffix - - Suffix to attach to the element ID of the injected template, will be ``_`` if not provided and not - the first template of the type, with ``index`` counting from 1 and increasing for each template of the same - type. - * - div - - Id for the div containing the component. If not provided, defaults to ``plugin_`` plus - the suffix if provided or required. - * - replaces - - Id of tab component this one replaces, might be either one of the core components or a component - provided by another plugin. See :ref:`this section ` for more on replacing template components. - * - custom_bindings - - A boolean value indicating whether the default view model should be bound to the tab pane and link - in the navigation (``false``) or if a custom binding will be used by the plugin (``true``, default). - * - data_bind - - Additional knockout data bindings to apply to the template container, can be used to add further behaviour to - the container based on internal state if necessary. - * - classes - - Additional classes to apply to both the wrapper around the sidebar box as well as the content pane itself, as a - list of individual classes (e.g. ``classes=["myclass", "myotherclass"]``) which will be joined into the correct - format by the template engine. * - classes_link - Like ``classes`` but only applied to the link in the navigation. * - classes_content - Like ``classes`` but only applied to the content pane itself. - * - styles - - Additional CSS styles to apply to both the wrapper around the sidebar box as well as the content pane itself, - as a list of individual declarations (e.g. ``styles=["color: red", "display: block"]``) which will be joined - into the correct format by the template engine. * - styles_link - Like ``styles`` but only applied to the link in the navigation. * - styles_content - Like ``styles`` but only applied to the content pane itself. - ``settings`` type - .. figure:: ../images/template-plugin-type-settings.png - :align: center - :alt: Structure of settings plugins - - Structure of settings plugins - - Configures a settings component to inject. The value must be a dictionary, supported values are the following: - - .. list-table:: - :widths: 5 95 - - * - name - - The name under which to include the settings pane, if not set the name of the plugin will be used. - * - template - - Name of the template to inject, defaults to ``_settings.jinja2``. - * - suffix - - Suffix to attach to the element ID of the injected template, will be ``_`` if not provided and not - the first template of the type, with ``index`` counting from 1 and increasing for each template of the same - type. - * - div - - Id for the div containing the component. If not provided, defaults to ``plugin_`` plus - the suffix if provided or required. - * - replaces - - Id of settings component this one replaces, might be either one of the core components or a component - provided by another plugin. See :ref:`this section ` for more on replacing template components. - * - custom_bindings - - A boolean value indicating whether the default settings view model should be bound to the settings pane and link - in the navigation (``false``) or if a custom binding will be used by the plugin (``true``, default). - * - data_bind - - Additional knockout data bindings to apply to the template container, can be used to add further behaviour to - the container based on internal state if necessary. - * - classes - - Additional classes to apply to both the wrapper around the navigation link as well as the content pane itself, as a - list of individual classes (e.g. ``classes=["myclass", "myotherclass"]``) which will be joined into the correct - format by the template engine. - * - classes_link - - Like ``classes`` but only applied to the link in the navigation. - * - classes_content - - Like ``classes`` but only applied to the content pane itself. - * - styles - - Additional CSS styles to apply to both the wrapper around the navigation link as well as the content pane itself, - as a list of individual declarations (e.g. ``styles=["color: red", "display: block"]``) which will be joined - into the correct format by the template engine. - * - styles_link - - Like ``styles`` but only applied to the link in the navigation. - * - styles_content - - Like ``styles`` but only applied to the content pane itself - - ``generic`` type - Configures a generic template to inject. The following keys are supported: - - .. list-table:: - :widths: 5 95 - - * - template - - Name of the template to inject, defaults to ``.jinja2``. - .. note:: As already outlined above, each template type has a default template name (i.e. the default navbar template @@ -452,6 +368,28 @@ class TemplatePlugin(OctoPrintPlugin): those, since the implicit default template will only be included automatically if no other templates of that type are defined. + Example: If you have a plugin that injects two tab components, one defined in the template file + ``myplugin_tab.jinja2`` (the default template) and one in the template ``myplugin_othertab.jinja2``, you + might be tempted to just return the following configuration since one your templates is named by the default + template name: + + .. code-block:: python + + return [ + dict(type="tab", template="myplugin_othertab.jinja2") + ] + + This will only include the tab defined in ``myplugin_othertab.jinja2`` though, ``myplugin_tab.jinja2`` will + not be included automatically since the presence of a defintion for the ``tab`` type overrides the automatic + injection of the default template. You'll have to include it explicitely: + + .. code-block:: python + + return [ + dict(type="tab", template="myplugin_tab.jinja2"), + dict(type="tab", template="myplugin_othertab.jinja2") + ] + :return list: a list containing the configuration options for the plugin's injected templates """ return []