{# partials/components/mobile_card_macros.html Wiederverwendbare Bausteine für modulspezifische Mobile-Karten ({modul}/partials/mobile_cards.html). Nutzen dieselben CSS-Klassen wie der generische Fallback (partials/lists/mobile_cards_generic.html) -- .m-card, .m-card-header, .m-card-meta, .m-card-meta-row, .m-card-footer, siehe app.css "Mobile Karten"-Abschnitt. Zweck: eigene, feinabgestimmte Karten pro Modul (statt des generischen, aber undifferenzierten Fallbacks), ohne dass jede mobile_cards.html das Karten-Markup komplett neu erfindet. Verwendung (Beispiel): {% import 'partials/components/mobile_card_macros.html' as mc %} {% for item_id, item in cfg.items() %} {% set _footer %} {{ mc.m_card_actions_default(module, item_id, item, container_id, loading_id) }} {% endset %} {% call mc.m_card(item.description or item_id, status=item.get('last_status'), footer=_footer) %} {{ mc.m_card_row('Ziel', item.get('target_path')) }} {% endcall %} {% endfor %} Wichtig: footer wird als ECHTES Kind-Element von .m-card gerendert (nicht als Sibling-Div daneben) -- Aktions-Buttons sollen sichtbar Teil der Karte sein, nicht nur optisch per CSS angeglichen. #} {% import 'partials/components/ui_macros.html' as ui %} {# Karten-Wrapper: Titel + optionaler Status im Header, caller() liefert die Meta-Zeilen (via m_card_row). Ohne caller-Body wird kein .m-card-meta gerendert (z.B. wenn eine Karte nur Header+Footer braucht). footer (vorgerenderter, bereits escapeter HTML-String -- z.B. via {% set %}... {% endset %} oder m_card_actions_default()) landet als .m-card-footer INNERHALB derselben Karte, nicht als separates Sibling-Element. #} {% macro m_card(title, status=none, enabled=True, footer=none) %}
{{ title }} {% if status %}{{ ui.status_inline(status) }}{% endif %}
{% if caller is defined %}
{{ caller() }}
{% endif %} {% if footer %} {% endif %}
{% endmacro %} {# Eine Label/Value-Zeile -- rendert nichts wenn value leer ist (wie der generische Fallback: keine leeren Meta-Zeilen anzeigen). #} {% macro m_card_row(label, value) %} {% if value %}
{{ label }} {{ value }}
{% endif %} {% endmacro %} {# Muster "Remote-Path-Paar" (Quelle/Ziel) -- borg, rsync. #} {% macro m_card_remote_path_pair(source_label, source_value, target_label, target_value) %} {{ m_card_row(source_label, source_value) }} {{ m_card_row(target_label, target_value) }} {% endmacro %} {# Footer-Wrapper -- caller() liefert die Buttons. #} {% macro m_card_footer() %} {% endmacro %} {# Standard-CRUD-Footer: card_actions (modul.yaml) + Edit + Delete, wie der generische Fallback. Deckt Muster 3 (reines CRUD) direkt ab. #} {% macro m_card_actions_default(module, item, item_data, container_id, loading_id, item_prefix='', has_edit=True, has_delete=True, card_actions=[]) %} {% for action in card_actions %}{{ ui.card_action_button(action, item, item_data, container_id, loading_id) }}{% endfor %} {% if has_edit %}{{ ui.edit_button(module=module, item=item, container_id=container_id, loading_id=loading_id, item_prefix=item_prefix) }}{% endif %} {% if has_delete %}{{ ui.delete_button(module=module, item=item, container_id=container_id, loading_id=loading_id, description=item_data.get('description') or item, item_prefix=item_prefix) }}{% endif %} {% endmacro %} {# Build/Run-Footer: Run-Button zusätzlich zu Edit/Delete -- Muster 5 (proxmox_client, builder, packages). #} {% macro m_card_run_actions(module, item, item_data, container_id, loading_id, item_prefix='', has_edit=True, has_delete=True, card_actions=[]) %} {{ ui.run_button(module=module, item=item, container_id=container_id, enabled=item_data.get('enabled', True)) }} {{ m_card_actions_default(module, item, item_data, container_id, loading_id, item_prefix, has_edit, has_delete, card_actions) }} {% endmacro %}