{% extends editor_base_template|default:"pretixcontrol/event/base.html" %} {# Owner: frontend-dev (ORCHESTRIERUNG.md section 5) #} {% comment %} The editor shell. Bootstrap 3 markup and Font Awesome icons, both from the control panel's own stack; no CDN, no bundler. All behaviour lives in static/pretix_custom_reports/js/report-editor.js, all data in the JSON blob at the bottom -- the control panel's CSP forbids inline script. The base template is a context variable because two views render this page: ReportEditorView below an event (pretixcontrol/event/base.html) and TemplateEditorView below an organizer (pretixcontrol/organizers/base.html). Both leave "content" to the page; the organizer base only wraps an extra "inner" block inside it, which this page does not use. Layout, after user feedback that everything was there but cramped and in no particular order: four blocks with a rule between them, in the order the work actually happens -- what the report is called, what goes into it, how it is arranged, what comes out. Every element id is unchanged, because report-editor.js addresses all of them by id. Every comment spanning more than one line in this file is a comment tag and not the short brace-hash form. Django's lexer only recognises the short form when the opener and the closer sit on the same line (verified against the Django in this venv), so a multi-line one is not a comment at all: it renders itself into the page as visible text. That happened here and a user found it. tests/test_editor_api.py::test_the_editor_page_renders_no_raw_django_comment keeps it from happening twice. {% endcomment %} {% load i18n %} {% load static %} {% load escapejson %} {% block title %} {% if is_template %}{% trans "Template editor" %}{% else %}{% trans "Report editor" %}{% endif %} {% endblock %} {% block custom_header %} {{ block.super }} {% endblock %} {% block content %}

{% if is_template %}{% trans "Template editor" %}{% else %}{% trans "Report editor" %}{% endif %}

{% comment %} The reference-event hint lives inside #pcr-editor on purpose: the "you have unsaved changes" guard binds to "#pcr-editor a[data-pcr-leave]", so a link outside would leave the page without asking. {% endcomment %} {% if is_template and reference_event %}
{% blocktrans trimmed with name=reference_event.name %} Reference event: {{ name }} {% endblocktrans %}
{% blocktrans trimmed %} A template has no event of its own, so the field library, the validation and the preview below come from this event. Fields marked “event values” have filter values that only exist in this event and are remapped when the template is loaded somewhere else. {% endblocktrans %} {% if choose_event_url %} {% trans "Use a different reference event" %} {% endif %}
{% endif %} {# ------------------------------------------------- 1: what it is #}

{% trans "Name and report base" %} {% if is_template %} {% trans "What this template is called and what one row of it stands for." %} {% else %} {% trans "What this report is called and what one row of it stands for." %} {% endif %}

{% csrf_token %}
{% if report_identifier %} {% endif %}
{% if not save_url %} {% if is_template %} {% blocktrans trimmed %} You cannot save this template: either you may not change this organizer's settings, or the template views are not reachable in this installation. Copy the JSON from the panel at the bottom in the meantime. {% endblocktrans %} {% else %} {% blocktrans trimmed %} You cannot save this report: either you may view reports but not change them, or the report views are not reachable in this installation. Copy the JSON from the panel at the bottom in the meantime. {% endblocktrans %} {% endif %} {% endif %}
{% comment %} Deliberately outside #pcr-form: report-editor.js renders radio buttons in here and posts the chosen base through the hidden #pcr-base-input, so these controls must not be form fields. {% endcomment %}

{% trans "Report base" %}


{# ---------------------------------------------- 2: what is in it #}

{% trans "Content" %} {% comment %} Filters sit in this block rather than with sorting: like the columns they are built by dragging a field out of the library on the left, and together with the columns they answer the one question "what ends up in the report". Sorting and the options only rearrange that result. {% endcomment %} {% trans "Which fields become columns, and which rows are included." %}

{# ------------------------------------------------ left column #}

{% trans "Field library" %}

{% blocktrans trimmed %} Drag a field into the column list, or use the buttons to add it as a column, filter or sorting stage. {% endblocktrans %}

{# ----------------------------------------------- right column #}

{% trans "Columns" %} 0

{% blocktrans trimmed %} No columns yet. Drag fields here from the field library. {% endblocktrans %}

{% trans "Order" %} {% trans "Field" %} {% trans "Column title" %} {% trans "Aggregate" %} {% trans "Format" %} {% trans "Actions" %}

{% trans "Filters" %}

{% blocktrans trimmed %} No filters: the report covers every order of this event. {% endblocktrans %}

{% blocktrans trimmed %} One level of grouping is available: conditions at the top level are combined with each other, and each group is combined as one condition. {% endblocktrans %}


{# ------------------------------------ 3: how the result is arranged #}

{% trans "Sorting and options" %} {% trans "The order of the rows, and which rows count at all." %}

{% trans "Sorting" %} 0

{% blocktrans trimmed %} No sorting: rows come in whatever order the database returns them. {% endblocktrans %}

{% trans "Order" %} {% trans "Field" %} {% trans "Direction" %} {% trans "Actions" %}

{% trans "Options" %}


{# --------------------------------------------- 4: what comes out #}

{% trans "Result" %} {% trans "What this report produces right now." %}

{# ------------------------------------------------------- preview #}

{% trans "Live preview" %}

{% if is_template and reference_event %}

{% blocktrans trimmed with name=reference_event.name %} The preview shows real orders of the reference event “{{ name }}”. A template itself has no data; only a copy loaded into an event does. {% endblocktrans %}

{% endif %}

{# ---------------------------------------------------------- JSON #}

{% trans "Definition as JSON" %}

{% blocktrans trimmed %} This is exactly what gets stored. You can paste a definition here and apply it. {% endblocktrans %}

{% comment %} File import/export and templates live in views/portability.py and views/templates.py (portability-dev). Every one of these links leaves the editor, so report-editor.js asks first when there are unsaved changes -- data-pcr-leave marks them, and "export" gets the sharper warning because the file is built from the stored row, not from what is on screen. In template mode only "export" is offered: there is no organizer-level file import, and loading a template into a template is meaningless. views/editor.py decides that, this page only renders what it is given. {% endcomment %} {% comment %} The block also renders when there is no button at all, which happens exactly once: an unsaved template, where export needs a stored row and neither import nor "load a template" exists. The help text below is then the whole point -- it says why there is nothing here yet. {% endcomment %} {% if portability.export or portability.import or portability.templates or is_template %}
{% if portability.export or portability.import or portability.templates %}
{% if portability.export %} {% trans "Export as a file" %} {% endif %} {% if portability.import %} {% trans "Import from a file" %} {% endif %} {% if portability.templates %} {% trans "Load a template" %} {% endif %}
{% endif %}

{% if portability.export %} {% blocktrans trimmed %} The exported file contains the saved report, not the changes you have not saved yet. {% endblocktrans %} {% elif is_template %} {% blocktrans trimmed %} Save this template to be able to export it as a file. {% endblocktrans %} {% else %} {% blocktrans trimmed %} Save this report to be able to export it as a file. {% endblocktrans %} {% endif %} {% if portability.import or portability.templates %} {% blocktrans trimmed %} Importing a file or loading a template opens a separate page and replaces what you see here. {% endblocktrans %} {% endif %}

{% endif %}
{% comment %} The second save button. form="pcr-form" submits the form up in block 1 without nesting anything (HTML5 form owner attribute), so the page keeps exactly one form and report-editor.js keeps its single submit handler. Both buttons carry the class pcr-save so that anything which wants to address "the save buttons" can do so without knowing there are two. {% endcomment %}
{% endblock %}