{# Results -- These macros are designed for handling the listing/results pages and the different formats that the content can be listed. They should be called like so: -------------------------------------------------------------------------------- {%- import "macros/results.html" as _results -%} {{ _results.filter(form) }} {{ _results.list( form, page, headings=headings, columns=columns, action=decor.result_action ) }} {{ _results.paging(form, paginator, page) }} -------------------------------------------------------------------------------- The `list` macro accepts a `headings` and `columns` value. These should be provided as macros containing a list of the headings/data columns like so: -------------------------------------------------------------------------------- {% macro headings() %} {{ _results.heading('Heading 1') }} {{ _results.heading('Heading 2', sort_with='heading_2') }} ... {% endmacro %} {% macro columns(item) %} {{ _results.column(item.item_1) }} {{ _results.column(item.item_2) }} ... {% endmacro %} -------------------------------------------------------------------------------- The values `form` and `page` must be passed. The `form` value is used to set the current sorted column. The `page` value is used to loop through and display each of the items, using the `columns` macro for each row. You can also pass through an `action` value. This allows you to set `data-mh-url` URL against the row (tr) which can then be made linkable using JS. #} {%- import "manhattan/manage/components/form.html" as _form with context -%} {# Filter -- A search form used to filter the results of a list page. The filter form requires that you pass a `form` value. This is used to generate the list of form filters. Everything passed to the filter macro is passed to and applied to the form macro inside it. -------------------------------------------------------------------------------- {{ _results.filter(form) }} -------------------------------------------------------------------------------- As standard you can also pass `class` to apply a custom class style to the containing element. You can also pass any other HTML attribute using keyword arguments and these will be applied to the container. -------------------------------------------------------------------------------- {{ _results.filter( form=form, action='/some-url', method='POST', class='some-class', **{'data-some-attribute': 'Some value'} ) }} -------------------------------------------------------------------------------- #} {% macro filter(form, action=None, method='GET', class=None) %} {%- set class = ' [ mh-filter ] [ mh-form--reverse-optional mh-form--fixed-btns-disabled ] ' + (' ' + class if class else '') -%} {%- call _form.form( form, action=action, method=method, class=class, **kwargs ) -%} {# Filter fields -- Loop through all form fields provided and show them appropriately unless they are the q field, page field, or within the advanced filters field. Also, we convert the sort_by field to a hidden field as ordering is achieved with javascript. #} {%- for field in form if not field.name in ['q', 'page', 'filters'] -%} {%- if field.name == 'sort_by' -%} {%- elif field.type != 'HiddenField' -%} {{ _form.field(field, class='mh-filter__field') }} {%- endif -%} {%- endfor -%} {%- if form.filters and form.filters._inline -%} {%- for field in form.filters -%} {{ _form.field(field, class='mh-filter__field') }} {%- endfor -%} {%- endif -%} {# Common field class -- The last field in the filter can contain the q field, the search button, and advanced filter dropdown. Given this, we need to format it differently depending on whether or not these exist. This is done by setting different classes against the common field. #} {%- set common_class = 'mh-filter__common' + (' mh-filter__common--has-q' if form.q else '') + (' mh-filter__common--has-adv-filter' if (form.filters and not form.filters._inline) else '') -%} {%- call _form.field(class=common_class) -%} {# Keyword field -- If there is a `q` field in the filter, it is manually inserted into the common field next to the search button. #} {%- if form.q -%} {{ _form.control(form.q) }} {%- endif -%} {# Search button -- Only show the search button if there are fields that are not a hidden field or not in the excluded list. #} {%- if form._info.show_search_button -%} {%- endif -%} {# Advanced filter -- If used, an advanced filter button appears to the right of the search field allowing the user to toggle the filter form in a dropdown. #} {%- if form.filters and not form.filters._inline -%} {{ advanced_filter(form) }} {%- endif -%} {%- endcall -%} {%- endcall -%} {% endmacro %} {% macro advanced_filter(form) %}
Filter {%- if form._info.filters_applied -%} {%- endif -%}
{%- call _form.fieldset('Advanced filter') -%}
{%- for field in form.filters -%} {%- if _form.field_types[field.type] == 'hidden' -%} {{ _form.input(field) }} {%- else -%} {{ _form.field(field, required=true) }} {%- endif -%} {%- endfor -%} {# Advanced filter button(s) -- If there are filters applied a clear button is added to the form allowing the user to reset the form. #} {%- if form._info.filters_applied -%} {%- call _form.buttons() -%} {{ _form.button('Update') }} {{ _form.button( 'Clear', class='mh-btn--grey', url=(form.reset_url or request.base_url) ) }} {%- endcall -%} {%- else -%} {{ _form.button('Update') }} {%- endif -%} {%- endcall -%}
{% endmacro %} {# Default columns -- A list of data columns shown within a table row. This macro is used in conjunction with the `list` macro as a default list of columns for every item in `page.items`. The macro can simply be overwritten in the local template with data custom to that page like so: -------------------------------------------------------------------------------- {% macro columns(item) -%} {{ column(item.name) }} {{ column(item.location) }} {{ column(item.date) }} ... {%- endmacro %} -------------------------------------------------------------------------------- #} {% macro columns(item) %} {{ column(item.__str__()) }} {% endmacro %} {# List -- The `list` macro provides an easy way of displaying data in a tabular format. You must pass `form` and `page` to the macro. The `form` value is used to set the `data-mh-sorted-by` attribute against the table if there is a form filter and a `sort_by` field in the filter. This can then be used to re-set the order of the listing using Javascript. The `page` value is used to loop through all of the items on the page using `page.items`. By default the table does not have any headings, and a row containing a single column is used for every item. However, you can overide this behaviour in the local template like so: -------------------------------------------------------------------------------- {% macro headings() -%} {{ _results.heading('Heading 1') }} {{ _results.heading('Heading 2', sort_with='heading_2') }} ... {%- endmacro %} {% macro columns(item) -%} {{ _results.column(item.item_1) }} {{ _results.column(item.item_2) }} ... {%- endmacro %} {{ _results.list( form, page, headings=headings, columns=columns, action=decor.result_action ) }} -------------------------------------------------------------------------------- If you want to add a link to each table row you can optionally pass an `action` value. As we can't set the individual links for each row, `item` is passed to the `action` value in order to generate a `data-mh-url` attribute against the row, which can then be made linkable using JS. As standard you can also pass `class` to apply a custom class style to the containing list element. You can also pass any other HTML attribute using keyword arguments and these will be applied to the container. -------------------------------------------------------------------------------- {{ _results.list( form=form, page=page, headings=headings, columns=columns, action=decor.result_action, fallback_text='No results', class='some-class', **{'data-some-attribute': 'Some value'} ) }} -------------------------------------------------------------------------------- #} {% macro list( form, page, headings=None, columns=columns, action=None, fallback_text='No results', class=None ) %}
{% if headings and page.items %} {{ headings() }} {% endif %} {%- for item in page.items -%} {% set action_link = None or (action(item) if action) %} {{- columns(item) -}} {% else %} {%- endfor -%}
{{ fallback_text }}
{% endmacro %} {# Heading -- A table heading (th) cell element. should be positioned at the top of the table inside of a thead element. Pass `text` through to set the text value shown for the heading. You can also pass a `sort_with` value to set what value this column is sorted by. -------------------------------------------------------------------------------- {{ _results.heading('My heading', sort_with='my_heading') }} -------------------------------------------------------------------------------- As standard you can also pass `class` to apply a custom class style to the containing element. You can also pass any other HTML attribute using keyword arguments and these will be applied to the container. -------------------------------------------------------------------------------- {{ _results.heading( text='My heading', sort_with='my_heading', make_safe=False, class='some-class', **{'data-some-attribute': 'Some value'} ) }} -------------------------------------------------------------------------------- #} {% macro heading(text=None, sort_with=None, make_safe=True, class=None) -%}
{% if caller %} {{ caller() }} {% else %} {{ text|safe if make_safe else text }} {% endif %}
{%- endmacro %} {# Column -- A table data (td) cell element. You can pass a `text` value through and the macro will try to determine what has been passed and display it in the most appropriate way possible. For example, if a list is passed, it will return a comma separated string. If nothing is passed, or a false/None value is passed, it will return `--`, however this fallback value can be overwritten by passing what you would prefer it to read as `fallback_text`. If you are not setting a URL against the row, then you can optionally send `url` through here. This will wrap the value in an tag. -------------------------------------------------------------------------------- {{ _results.column('My value', url='/my-url', fallback_text='Read more...') }} -------------------------------------------------------------------------------- As standard you can also pass `class` to apply a custom class style to the containing element. You can also pass any other HTML attribute using keyword arguments and these will be applied to the container. -------------------------------------------------------------------------------- {{ _results.column( text='My value', url='/my-url', fallback_text='Read more...', make_safe=False, class='some-class', **{'data-some-attribute': 'Some value'} ) }} -------------------------------------------------------------------------------- #} {% macro column( text, url=None, fallback_text='--', make_safe=True, class=None ) -%} {%- if caller -%} {{ caller() }} {%- elif text -%} {{ ('')|safe if url }} {%- if text is iterable and not text is string -%} {%- for t in text -%} {{ t|safe if make_safe else t }} {%- if not loop.last %}, {% endif -%} {%- endfor -%} {%- else -%} {{ text|safe if make_safe else text }} {%- endif -%} {{ ''|safe if url }} {%- else -%} {{ fallback_text }} {%- endif -%} {% endmacro%} {# Paging -- Navigation buttons and jump to form which allow the user to navigate through a list using paging. The paging macro requires `form`, `page`, and `paginator`. -------------------------------------------------------------------------------- {{ _results.paging(form, paginator, page) }} -------------------------------------------------------------------------------- #} {% macro paging(form, paginator, page) %} {% set params = form._info.paging_query_string %} {% endmacro %}