diff --git a/docs/narr/index.rst b/docs/narr/index.rst index 20f3a85..f9beea1 100644 --- a/docs/narr/index.rst +++ b/docs/narr/index.rst @@ -2,15 +2,7 @@ Documentation ============= -TODO +.. toctree:: + :maxdepth: 2 -.. - .. toctree:: - :maxdepth: 2 - - install/index - config/index - cli/index - handlers/index - providers/index - db/index + templates/index diff --git a/docs/narr/templates/base.rst b/docs/narr/templates/base.rst new file mode 100644 index 0000000..554c721 --- /dev/null +++ b/docs/narr/templates/base.rst @@ -0,0 +1,251 @@ + +Base Templates +============== + +This describes the base templates. When creating a custom page +template, you most often need to inherit from one of these: + +* :ref:`page_base_template` +* :ref:`form_base_template` +* :ref:`master_base_templates` + +.. note:: + + Any of these templates may be overridden; see + :ref:`mako-template-override`. + + +Global Base +~~~~~~~~~~~ + +There is exactly one "true base template" for the web app, designated +as: ``/base.mako`` + +The default base template is ``wuttaweb:templates/base.mako`` and all +page templates inherit from it. However they inherit it by *name* +only (``/base.mako``) - therefore if you override this via custom +template search paths, effectively you have changed the **theme**. + +In addition to general layout/structure, this template is reponsible +for creating the Vue app which encompasses the whole of every page. +It also establishes the ``WholePage`` component which is the Vue app's +one and only child component. + +(``WholePage`` in turn will have other children, for page content.) + +There is usually no need to define a template which inherits directly +from ``/base.mako``, rather you should inherit from ``/page.mako`` +(see next section) or similar. + +As pertains to Vue component logic, there are 3 blocks which you may +find a need to override. These are defined by ``/base.mako`` so will +apply to *all* templates: + +* ``render_vue_templates()`` +* ``modify_vue_vars()`` +* ``make_vue_components()`` + +Most often it is necessary to customize ``modify_vue_vars()`` but keep +reading for an example. + + +.. _page_base_template: + +Page Base +~~~~~~~~~ + +The common base template for pages, designated as: ``/page.mako`` + +This extends the Vue logic from ``/base.mako`` by establishing +``ThisPage`` component, which wraps all content within the current +page. + +The final structure then is conceptually like: + +.. code-block:: html + +
+ + + + + + +
+ +Simple usage is to create a template which inherits from +``/page.mako`` and defines a ``page_content()`` block, e.g.: + +.. code-block:: mako + + <%inherit file="/page.mako" /> + + <%def name="page_content()"> +

hello world!

+ + +The default ``/page.mako`` logic knows where to render the +``page_content()`` block so that it fits properly into the +component/layout structure. + +Often you may need to customize Vue component logic for a page; this +is done by defining one of the blocks mentioned in previous section. + +Here is a simple example which shows how this works: + +.. code-block:: mako + + <%inherit file="/page.mako" /> + + <%def name="page_content()"> + + + + + + Alert + + + + + <%def name="modify_vue_vars()"> + ${parent.modify_vue_vars()} + + + +You can see that ``page_content()`` is able to reference things from +``ThisPage`` component, while the ``modify_vue_vars()`` block is used +to define those same things on the component. + + +.. _form_base_template: + +Form Base +~~~~~~~~~ + +The common base template for pages with a form, designated as: +``/form.mako`` + +This expects the context dict to contain ``'form'`` which points to a +:class:`~wuttaweb.forms.base.Form` instance. + +This template extends the Vue logic from ``/page.mako`` by +establishing a Vue component specific to the form object. + +The final structure then is conceptually like: + +.. code-block:: html + +
+ + + + + + + + +
+ +A simple example which assumes one of the form fields exposes a button +with click event that triggers ``alertFoo()`` method on the form +component: + +.. code-block:: mako + + <%inherit file="/form.mako" /> + + <%def name="modify_vue_vars()"> + ${parent.modify_vue_vars()} + + + +.. note:: + + By default, ``${form.vue_compoment}`` is rendered as ``WuttaForm`` + but that is not guaranteed. You should resist the temptation to + hard-code that; always use ``${form.vue_component}`` and (where + applicable) ``${form.vue_tagname}``. + + The reason for this is to allow multiple forms to exist on a single + page, each with a separate Vue component. (Which is not shown in + the above example.) + + See also :attr:`~wuttaweb.forms.base.Form.vue_component` and + :attr:`~wuttaweb.forms.base.Form.vue_tagname`. + + +.. _master_base_templates: + +Master Base +~~~~~~~~~~~ + +These templates are for use with +:class:`~wuttaweb.views.master.MasterView`. Each is the default +template used for the corresponding route/view, unless a more specific +template is defined. + +The "index" template is unique in that it is (usually) for listing the +model data: + +* ``/master/index.mako`` + +The "form" template is just a base template, does not directly +correspond to a route/view. Other CRUD templates inherit from it. +This inherits from ``/form.mako`` (see previous section). + +* ``/master/form.mako`` + +These CRUD templates inherit from ``/master/form.mako`` and so +require a ``'form'`` in the context dict. + +* ``/master/create.mako`` +* ``/master/view.mako`` +* ``/master/edit.mako`` +* ``/master/delete.mako`` + +The "configure" template is for master views which have a +configuration page. + +* ``/master/configure.mako`` + +Usage for these is not significantly different from the ones shown +above, in cases where you actually need to override the template. + +As an example let's say you have defined a ``WidgetMasterView`` class +and want to override its "view" template. You would then create a +file as ``/widgets/view.mako`` (within your templates folder) and +be sure to inherit from the correct base template: + +.. code-block:: mako + + <%inherit file="/master/view.mako" /> + + <%def name="page_content()"> + +

THIS APPEARS FIRST!

+ + ## nb. the form will appear here + ${parent.page_content()} + +

MADE IT TO THE END!

+ + diff --git a/docs/narr/templates/index.rst b/docs/narr/templates/index.rst new file mode 100644 index 0000000..d560666 --- /dev/null +++ b/docs/narr/templates/index.rst @@ -0,0 +1,10 @@ + +Templates +========= + +.. toctree:: + :maxdepth: 2 + + overview + base + lookup diff --git a/docs/narr/templates/lookup.rst b/docs/narr/templates/lookup.rst new file mode 100644 index 0000000..11247c2 --- /dev/null +++ b/docs/narr/templates/lookup.rst @@ -0,0 +1,69 @@ + +Template Lookup +=============== + +The discovery of templates is handled by Mako, and is configurable. + +WuttaWeb comes with all templates it needs, in the path designated as +``wuttaweb:templates``. + +When the app renders a page, it invokes the Mako lookup logic, which +searches one or more folders and returns the first matching file it +encounters. By default ``wuttaweb:templates`` is the only place it +looks. + +A template is searched for by "name" but it is more path-like, e.g. +``/page.mako`` or ``/master/index.mako`` etc. So for example the file +at ``wuttaweb:templates/home.mako`` is used for home page (using +lookup name ``/home.mako``) by default. + + +.. _mako-template-override: + +Overriding the Search Paths +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The basic idea is to give it a list of paths it should search when +trying to find a template. The first template file found for a given +search name is used and no further search is done for that name. + +You can define the Mako lookup sequence in your ``web.conf`` as +follows: + +.. code-block:: ini + + [app:main] + mako.directories = + /random/path/on/disk + poser.web:templates + wuttaweb:templates + +This setting is interpreted by ``pyramid_mako`` (`docs`_). + +.. _docs: https://docs.pylonsproject.org/projects/pyramid_mako/en/latest/index.html#mako-directories + +Here ``wuttaweb:templates/home.mako`` would still be used by default +for home page, *unless* e.g. ``/random/path/on/disk/home.mako`` +existed in which case that would be used. + +Each path can have an arbitrary set of templates, they will +effectively be combined to a single set by the app, with the +definition order determining search priority. + +If you are already using a custom ``app.main()`` function for +constructing the web app during startup, it may be a good idea to +change the *default* search paths to include your package. + +Setup for custom ``app.main()`` is beyond the scope here, but assuming +you *do* already have one, this is what it looks like:: + + from wuttaweb import app as base + + def main(global_config, **settings): + + # nb. set the *default* mako search paths; however config can + # still override with method shown above + settings.setdefault('mako.directories', ['poser.web:templates', + 'wuttaweb:templates']) + + return base.main(global_config, **settings) diff --git a/docs/narr/templates/overview.rst b/docs/narr/templates/overview.rst new file mode 100644 index 0000000..4801e17 --- /dev/null +++ b/docs/narr/templates/overview.rst @@ -0,0 +1,15 @@ + +Overview +======== + +WuttaWeb uses the `Mako`_ template language for page rendering. + +.. _Mako: https://www.makotemplates.org/ + +There is a "global" base template which effectively defines the +"theme" (page layout, Vue component structure). A few other base +templates provide a starting point for any custom pages; see +:doc:`base`. + +Templates are found via lookup which is handled by Mako. This is +configurable so you can override any or all; see :doc:`lookup`. diff --git a/src/wuttaweb/templates/appinfo/configure.mako b/src/wuttaweb/templates/appinfo/configure.mako index 1ea6481..da7d94d 100644 --- a/src/wuttaweb/templates/appinfo/configure.mako +++ b/src/wuttaweb/templates/appinfo/configure.mako @@ -140,8 +140,8 @@ -<%def name="modify_this_page_vars()"> - ${parent.modify_this_page_vars()} +<%def name="modify_vue_vars()"> + ${parent.modify_vue_vars()} diff --git a/src/wuttaweb/templates/auth/login.mako b/src/wuttaweb/templates/auth/login.mako index 6f07542..e6b77c6 100644 --- a/src/wuttaweb/templates/auth/login.mako +++ b/src/wuttaweb/templates/auth/login.mako @@ -19,7 +19,8 @@ -<%def name="modify_this_page_vars()"> +<%def name="modify_vue_vars()"> + ${parent.modify_vue_vars()} +<%def name="render_vue_script_whole_page()"> + + + <%def name="render_this_page_component()"> @@ -409,88 +468,25 @@ <%def name="render_prevnext_header_buttons()"> -<%def name="declare_whole_page_vars()"> - +<%def name="render_vue_templates()"> + ${self.render_vue_template_whole_page()} + ${self.render_vue_script_whole_page()} -<%def name="modify_whole_page_vars()"> +<%def name="modify_vue_vars()"> -<%def name="finalize_whole_page_vars()"> - -<%def name="make_whole_page_component()"> +<%def name="make_vue_components()"> ${make_wutta_components()} - ${self.render_whole_page_template()} - ${self.declare_whole_page_vars()} - ${self.modify_whole_page_vars()} - ${self.finalize_whole_page_vars()} - -<%def name="make_whole_page_app()"> +<%def name="make_vue_app()"> diff --git a/src/wuttaweb/templates/base_meta.mako b/src/wuttaweb/templates/base_meta.mako index c65e68c..65d1ede 100644 --- a/src/wuttaweb/templates/base_meta.mako +++ b/src/wuttaweb/templates/base_meta.mako @@ -1,8 +1,6 @@ ## -*- coding: utf-8; -*- -<%def name="app_title()">${app.get_title()} - -<%def name="global_title()">${self.app_title()} +<%def name="global_title()">${app.get_title()} <%def name="extra_styles()"> diff --git a/src/wuttaweb/templates/configure.mako b/src/wuttaweb/templates/configure.mako index 58b707e..d430672 100644 --- a/src/wuttaweb/templates/configure.mako +++ b/src/wuttaweb/templates/configure.mako @@ -134,8 +134,8 @@ -<%def name="modify_this_page_vars()"> - ${parent.modify_this_page_vars()} +<%def name="modify_vue_vars()"> + ${parent.modify_vue_vars()} - + -<%def name="modify_this_page_vars()"> - -<%def name="finalize_this_page_vars()"> - -<%def name="make_this_page_component()"> - ${self.declare_this_page_vars()} - ${self.modify_this_page_vars()} - ${self.finalize_this_page_vars()} - - - - -${self.render_this_page_template()} -${self.make_this_page_component()}