{# Content of a modal of the notes page, or of the planner's right panel (panel: one plan, feature or task). Every form posts to /notes/ (the same methods as the MCP tools, source "wiki") and the page comes back redrawn, with the same plans and item, which also closes a modal. #} {# A form sent from the panel answers into the panel; deleting the item shown (`whole`) answers with the page. #} {% macro post(action, confirm="", title="", whole=False) -%} hx-post="/notes/{{ action }}" hx-target="{% if panel and not whole %}#planner-detail{% else %}#content{% endif %}"{% if confirm %} hx-confirm="{{ confirm }}"{% endif %}{% if title %} data-confirm-title="{{ title }}"{% endif %} {%- endmacro %} {# A form that saves by itself: when a field changes (a text field when it is left), only the head and the plan cards come back, so nothing moves under the user. #} {% macro autosave(action) -%} hx-post="/notes/{{ action }}" hx-trigger="change" hx-swap="none" {%- endmacro %} {% macro keep() -%} {% if panel %}{% endif %} {%- endmacro %} {# A link that shows a note on its tab, closing the modal (the page comes back). #} {% macro ui_nav_note(ref) -%} href="/notes?tab={{ tab }}&selected={{ ref }}" hx-get="/notes?tab={{ tab }}&selected={{ ref }}" hx-target="#content" hx-push-url="true" {%- endmacro %} {# When a guideline is given to the agents; a hidden marker tells the server the boxes were shown. #} {% macro moment_boxes(chosen) -%}
Given to agents also when the code of its entities is read or edited
{% for moment in moments %}{% endfor %}
{%- endmacro %} {# Foot of a creation modal: Cancel closes it (live.js), the button on the right sends the form. #} {% macro dialog_foot(label) -%}
{%- endmacro %} {% macro lines(items) %}{{ items | join("\n") }}{% endmacro %} {% macro when(stamp) %}{% endmacro %} {% macro state(value) %}{{ value }}{% endmacro %} {# A section of the panel that folds; live.js remembers which ones were folded. #} {% macro section(name, title) -%}
{{ title }}
{{ caller() }}
{%- endmacro %} {# A button that opens the creation modal of the page. #} {% macro create_button(query, label) -%} {%- endmacro %} {# One feature or task of the list: its state and title, a pencil to open it here, a bin to delete it. #} {% macro child_row(child, kind) -%}
  • {{ state(child.state) }} {{ child.title }}
    {{ keep() }}
  • {%- endmacro %} {# Deleting, apart at the bottom; it asks first (the shared confirmation modal). #} {% macro danger(action, field, value, label, question) -%}
    {{ keep() }}
    {%- endmacro %} {% macro dependencies(item, choices) %} {% call section("waits", "Waits for") %} {% if item.depends_on %} {% else %}

    Nothing.

    {% endif %} {# Autocomplete with several values: type part of a name, pick items (Enter or click), each becomes a tag; one reason for all of them. The choices come as JSON; see live.js. #}
    {{ keep() }}
    {% endcall %} {% endmacro %} {% include "notes_head.html" %} {% if error %}

    {{ error }}

    {% endif %} {# --- New plan, feature or task #} {% if not item and kind == "plan" %}
    {{ keep() }}

    It starts with one feature and one task of the same title; add more from the plan.

    {{ dialog_foot("Create plan") }}
    {% elif not item and kind == "feature" %}
    {{ keep() }}

    It starts with one task of the same title.

    {{ dialog_foot("Add feature") }}
    {% elif not item and kind == "task" %}
    {{ keep() }} {{ dialog_foot("Add task") }}
    {# --- An existing plan #} {% elif item and kind == "plan" and item.fixed %} {# The Reviews plan: its own fields never change and it is never deleted; its features and tasks do. #} {% call section("general", "General") %}

    A fixed plan: commits made outside the commit flow come here as tasks, to be checked against the planning and the memory. It is hidden while it has no task.

    {{ item.title }}

    {{ item.goal }}

    {% endcall %} {% call section("features", "Features") %} {{ create_button("kind=feature&plan_id=" ~ item.id, "+ Add feature") }} {% endcall %} {% elif item and kind == "plan" %} {% call section("general", "General") %}
    {{ keep() }}

    Created {{ when(item.created) }} by {{ item.source }} · updated {{ when(item.updated) }}

    {% endcall %} {% call section("features", "Features") %} {{ create_button("kind=feature&plan_id=" ~ item.id, "+ Add feature") }} {% endcall %} {{ dependencies(item, choices) }} {{ danger("delete_item", "item", item.item, "Delete plan", "Delete the plan “" ~ item.title ~ "” with all its features and tasks? This cannot be undone.") }} {# --- An existing feature #} {% elif item and kind == "feature" %} {% call section("general", "General") %}
    {{ keep() }}

    Created {{ when(item.created) }} by {{ item.source }} · updated {{ when(item.updated) }}

    {% endcall %} {% call section("tasks", "Tasks") %} {{ create_button("kind=task&feature_id=" ~ item.id, "+ Add task") }} {% endcall %} {{ dependencies(item, choices) }} {{ danger("delete_item", "item", item.item, "Delete feature", "Delete the feature “" ~ item.title ~ "” with all its tasks? This cannot be undone.") }} {# --- An existing task #} {% elif item and kind == "task" %} {% call section("general", "General") %}
    {{ keep() }}

    Created {{ when(item.created) }} by {{ item.source }} · updated {{ when(item.updated) }}

    {% endcall %} {% call section("criteria", "Criteria") %} {% if item.criteria %} {% else %}

    No criteria yet: write them in General, one per line.

    {% endif %} {% endcall %} {% call section("evidence", "Evidence that it is done") %} {% if item.evidence %} {% else %}

    None yet.

    {% endif %} {# One field: Add records it as evidence; Approve as done closes the task with your approval, and Withdraw approval takes it back (the text, if any, goes with either). #}
    {{ keep() }} {% if item.status != "done" %} {% else %} {% endif %}
    {% endcall %} {% call section("annotations", "Annotations") %} {% if item.annotations %} {% else %}

    None yet.

    {% endif %}
    {{ keep() }}
    {% endcall %} {{ dependencies(item, choices) }} {{ danger("delete_item", "item", item.item, "Delete task", "Delete the task “" ~ item.title ~ "” with its annotations and evidence? This cannot be undone.") }} {# --- A new note #} {% elif kind == "note" and not note %} {% set group = "guidelines" if query.type in note_groups.guidelines else "memory" %} {% set filled = filled or {} %}
    {{ keep() }} {% if group == "guidelines" %}{{ moment_boxes(filled_moments or ["always"]) }}{% endif %} {% if similar %} {# The review before adding found notes close to this one: change one of them, or save this one anyway. #}

    Similar notes already exist. Open one to change or supersede it, or save this one anyway.

      {% for other in similar %}
    • {{ other.statement }} {{ other.type }} · {{ "%.2f" | format(other.score) }}
    • {% endfor %}
    {{ dialog_foot("Save anyway") }} {% else %} {{ dialog_foot("Create note") }} {% endif %}
    {# --- An existing note #} {% elif note %} {% if note.status == "active" %} {% call section("general", "General") %}
    {{ keep() }} {% if note.group == "guidelines" %}{{ moment_boxes(note.moments) }}{% endif %}

    {{ note.source }} · {{ when(note.updated) }}

    {% endcall %} {% call section("supersede", "It no longer holds: supersede it") %}
    {{ keep() }}
    {% endcall %} {{ danger("delete_note", "note_id", note.id, "Delete note", "Delete the note “" ~ (note.statement | truncate(90)) ~ "”? This cannot be undone; a note that stopped holding should be superseded instead.") }} {% else %}

    {{ note.statement }}

    {% if note.why %}

    {{ note.why }}

    {% endif %}

    Superseded{% if note.superseded_by %} by note #{{ note.superseded_by }}{% endif %}.

    {% endif %} {% endif %}