{# core/ui/templates/partials/components/ui_macros.html Generische UI-Makros – AstrapiFlaskUi V3 Standard-URL-Konventionen: CRUD: POST /api/{module}/{item}/run Debug: POST /api/{module}/{item}/run?debug=true Logs: GET /api/{module}/{item}/logs #} {% macro edit_button(module=None, item=None, container_id=None, loading_id=None, item_prefix='') %} {% endmacro %} {% macro delete_button(module=None, item=None, container_id=None, loading_id=None, description=None, item_prefix='') %} {% endmacro %} {% macro toggle_switch(module=None, item=None, container_id=None, loading_id=None, enabled=False, description=None) %} {% endmacro %} {% macro toggle_button(module=None, item=None, container_id=None, loading_id=None, enabled=False, description=None) %} {{ toggle_switch(module=module, item=item, container_id=container_id, loading_id=loading_id, enabled=enabled, description=description) }} {% endmacro %} {% macro add_button(module=None, container_id=None, loading_id=None) %} {% endmacro %} {% macro action_button(label, url, title=None, css_class="btn-ghost btn-sm", target="body", swap="beforeend") %} {% endmacro %} {% macro status_inline(status) %} {% set _s = status | lower if status else '' %} {% if _s == 'ok' %} OK {% elif _s == 'error' %} Fehler {% elif _s == 'warning' %} Warnung {% elif _s == 'running' or _s == 'building' %} läuft {% elif _s == 'pending' %} Pending {% elif _s %} {{ status }} {% else %} Neu {% endif %} {% endmacro %} {% macro refresh_button(endpoint="/", container_id=None, loading_id=None) %} {% endmacro %} {# ── Runnable-Modul-Makros ────────────────────────────────────────────────── #} {# Standard-Konvention: POST /api/{module}/{item}/run[?debug=true] #} {# GET /api/{module}/{item}/logs #} {% macro run_button(module=None, item=None, container_id=None, enabled=True) %} {% endmacro %} {% macro run_debug_button(module=None, item=None, container_id=None) %} {% endmacro %} {% macro settings_button(module=None) %} {% endmacro %} {% macro log_button(module=None, item=None) %} {% endmacro %} {# ── Modal-Standard-Komponenten ──────────────────────────────────────────── #} {# #} {# Jedes Modal soll denselben Aufbau haben: #} {# 1. modal_wrapper – Backdrop + innere Box (Außenstruktur) #} {# 2. modal_title – Icon + Überschrift (Header) #} {# 3. Inhalt – Formular, Text, Karten … #} {# 4. modal_footer – Toggle + Abbrechen/Speichern (Standard) #} {# oder modal_footer_simple – nur ein Schließen-Button #} {# #} {# Verwendung mit modal_wrapper: #} {# {% call modal_wrapper("mein-modal", max_width="580px") %} #} {# {{ modal_title(title="Titel", icon="edit") }} #} {# #} {# {{ modal_footer(save_label="Speichern") }} #} {# {% endcall %} #} {# modal_wrapper(id, max_width, padding) Rendert Backdrop + innere Modal-Box. Inhalt via {% call %}-Block. id – HTML-ID des Backdrop-Elements (ganzer Modal) max_width – CSS max-width der inneren Box (default: "620px") padding – CSS padding der inneren Box (default: "28px 32px") #} {% macro modal_wrapper(id, max_width="620px", padding="28px 32px") %}
{{ caller() }}
{% endmacro %} {# modal_title(title, icon, is_edit) Rendert den Header eines Modals. title – Anzeigetext icon – 'edit' | 'create' | 'settings' | 'log' | 'bell' | 'warning' | 'info' | 'none' is_edit – veraltet: Kurzform für icon='edit' (True) / icon='create' (False) #} {% macro modal_title(title='', icon=None, is_edit=False) %}
{{ title }}
{% endmacro %} {# modal_footer(enabled, enabled_id, save_label, save_disabled, has_toggle, save_id, save_type) Rendert den Standard-Footer eines Modals (Toggle + Abbrechen + Speichern). enabled – bool: aktueller Toggle-Zustand enabled_id – HTML-ID der versteckten Checkbox save_label – Text für den Speichern-Button save_disabled – bool: Speichern-Button deaktivieren has_toggle – bool: Toggle anzeigen (default True) save_id – optionale HTML-ID für den Speichern-Button save_type – "submit" (default) oder "button" (bei JS-Validierung) #} {% macro modal_footer(enabled=True, enabled_id='modal-enabled', save_label='Speichern', save_disabled=False, has_toggle=True, save_id=None, save_type='submit') %} {% endmacro %} {# modal_footer_simple(close_label) Rendert einen einfachen Footer mit nur einem Schließen-Button (z. B. Log-Modal). close_label – Beschriftung des Schließen-Buttons (default: "Schließen") #} {% macro modal_footer_simple(close_label="Schließen") %} {% endmacro %} {# icon(name) Rendert ein inline-SVG anhand des Icon-Namens (13×13 px). Wird von card_action_button() und extern verwendet. Bekannte Namen: search, bar-chart, play, bug, file-text, terminal, external-link, info, refresh #} {% macro icon(name) -%} {%- endmacro %} {# card_action_button(action, item, item_data, container_id, loading_id) Rendert einen Card-Footer-Button aus einer card_actions-Eintragsdefinition. action – Dict aus modul.yaml card_actions: title – Tooltip icon – Icon-Name (siehe icon()-Makro) style – optional: 'run', 'debug', 'log', 'danger' → btn-icon-{style} hx_get – HTMX GET-URL (alternativ zu hx_post) hx_post – HTMX POST-URL (alternativ zu hx_get) hx_headers – HTMX-Headers als JSON-String hx_target – HTMX-Target (default: #main-content) hx_swap – HTMX-Swap (default: innerHTML) hx_push_url – HTMX push-url disabled_if_off – bool: Button deaktivieren wenn item_data.enabled=false Platzhalter in URLs und hx_target: {item}, {description}, {container_id}, {loading_id} #} {% macro card_action_button(action, item, item_data={}, container_id='', loading_id='') %} {%- if not action.show_if_field or item_data.get(action.show_if_field) -%} {%- if not action.hide_if_field_value or item_data.get(action.hide_if_field_value.field) != action.hide_if_field_value.value -%} {%- set _subs = [ ('{item}', item | string), ('{description}', item_data.description | default(item | string)), ('{container_id}', container_id | string), ('{loading_id}', loading_id | string), ] -%} {%- macro _sub(s) -%} {%- set ns = namespace(v=s) -%} {%- for k, v in _subs %}{%- set ns.v = ns.v | replace(k, v) -%}{%- endfor -%} {{- ns.v -}} {%- endmacro -%} {%- if action.href -%} {{ icon(action.icon) }} {%- else -%} {%- endif -%} {%- endif -%} {%- endif %} {% endmacro %} {# ═══════════════════════════════════════════════════════════════════════════ #} {# Deklaratives UI-System – Render-Makros für controls.py-Dataklassen #} {# ═══════════════════════════════════════════════════════════════════════════ #} {# col_header(col) Rendert ein -Element für eine Col-Instanz aus controls.py. #} {% macro col_header(col) %}{{ col.label }} {% endmacro %} {# col_cell(col, item_name, item_data) Rendert ein -Element für eine Col-Instanz. col – controls.Col-Instanz item_name – String-Key des Eintrags item_data – Dict mit den Eintragsdaten #} {% macro col_cell(col, item_name, item_data) %} {%- set _val = item_data.get(col.key) if item_data is mapping else none -%} {%- if col.type == 'text' -%} {{ _val or '—' }} {%- elif col.type == 'trunc' -%} {{ _val or '—' }} {%- elif col.type == 'remote_path' -%} {%- set _rhost = resolve_remote_host(item_data.get(col.remote_key)) if item_data.get(col.remote_key) else '—' -%} {%- set _rlabel = 'Lokal' if _rhost == '—' else _rhost -%} {{ _rlabel }}:{{ item_data.get(col.path_key) or '—' }} {%- elif col.type == 'remote_host' -%} {%- set _rhost = resolve_remote_host(item_data.get(col.remote_key)) if item_data.get(col.remote_key) else '—' -%} {{ 'Lokal' if _rhost == '—' else _rhost }} {%- elif col.type == 'join' -%} {%- set _list = _val if (_val is iterable and _val is not string) else [] -%} {{ _list | join(col.sep) or '—' }} {%- elif col.type == 'mono' -%} {{ _val or '—' }} {%- elif col.type == 'badge_enum' -%} {%- set _bd = col.values.get(_val | string, {}) if col.values and _val else {} -%} {%- if _bd %}{{ _bd.label | default(_val) }} {%- elif _val %}{{ _val }} {%- else %}—{% endif -%} {%- elif col.type == 'badge_list' -%} {%- set _list = _val if (_val is iterable and _val is not string) else [] -%} {%- if _list -%}
{%- for v in _list -%} {%- set _bd = col.values.get(v | string, {}) if col.values else {} -%} {{ _bd.label | default(v) }} {%- endfor -%}
{%- else %}—{% endif -%} {%- elif col.type == 'link' -%} {%- if _val %}{{ _val }} {%- else %}—{% endif -%} {%- elif col.type == 'composed' -%} {%- set _composed = col.template | replace('{item_name}', item_name | string) | replace('{key}', _val | string) -%} {{ _composed if _val else '—' }} {%- elif col.type == 'status' -%} {{ status_inline(_val) }} {%- else -%} {{ _val or '—' }} {%- endif %} {% endmacro %} {# header_control(ctrl, module, container_id, loading_id) Rendert ein einzelnes Header-Control (filter_select oder action_button). ctrl – controls.HeaderControl-Instanz module – Modul-Key (String) container_id – Container-ID für Standard-HTMX-Target loading_id – Loading-Indicator-ID #} {% macro header_control(ctrl, module, container_id, loading_id='') %} {%- if ctrl.type == 'filter_select' -%} {%- set _hx_get = ctrl.hx_get or ('/ui/' ~ module ~ '/content') -%} {%- set _hx_target = ctrl.hx_target or ('#' ~ container_id) -%} {%- set _hx_swap = ctrl.hx_swap or 'innerHTML' -%} {%- set _hx_include = ctrl.hx_include or ('[data-filter-for=\'' ~ module ~ '\']') -%} {%- set _data_key = ctrl.data_attr or ('data-filter-for="' ~ module ~ '"') -%} {%- set _opts = ctrl.options if ctrl.options else [] -%} {%- if not _opts and ctrl.options_fn -%}{%- set _opts = ctrl.options_fn() -%}{%- endif -%} {%- elif ctrl.type == 'action_button' -%} {%- endif %} {% endmacro %}