diff --git a/inventory/templates/fragments/_combobox_fragment.html b/inventory/templates/fragments/_combobox_fragment.html index cc812ad..5bf940c 100644 --- a/inventory/templates/fragments/_combobox_fragment.html +++ b/inventory/templates/fragments/_combobox_fragment.html @@ -1,104 +1,84 @@ {% import "fragments/_icon_fragment.html" as icons %} -{% macro render_combobox(id, options, label=none, placeholder=none, onAdd=none, onRemove=none, onEdit=none, data_attributes=none) %} - +{% macro render_combobox(id, options, label=none, placeholder=none, onAdd=none, onRemove=none, onEdit=none, +data_attributes=none) %} + - {% if label %} - - {% endif %} -
-
- - - -
- +{% if label %} + +{% endif %} +
+
+ + +
+ +
- + {% endmacro %} {% macro dynamic_combobox( - id, options, label = none, placeholder = none, data_attributes = none, - create_url = none, edit_url = none, delete_url = none, refresh_url = none +id, options, label = none, placeholder = none, data_attributes = none, +create_url = none, edit_url = none, delete_url = none, refresh_url = none ) %} - {% if label %} - - {% endif %} -
-
- +{% if label %} + +{% endif %} +
+
+ - + - -
- - - - {% if refresh_url %} -
- {% endif %} +
-{% endmacro %} + + + + {% if refresh_url %} +
+ {% endif %} +
+{% endmacro %} \ No newline at end of file diff --git a/inventory/templates/fragments/_option_fragment.html b/inventory/templates/fragments/_option_fragment.html new file mode 100644 index 0000000..600edc5 --- /dev/null +++ b/inventory/templates/fragments/_option_fragment.html @@ -0,0 +1,6 @@ +{% for option in options %} + +{% endfor %} \ No newline at end of file diff --git a/inventory/templates/playground.html b/inventory/templates/playground.html index af7322e..af45727 100644 --- a/inventory/templates/playground.html +++ b/inventory/templates/playground.html @@ -2,17 +2,8 @@ {% block content %} {{ combos.dynamic_combobox( - 'play', - [ - { - 'id': 1, - 'name': 'Beans' - }, - { - 'id': 2, - 'name': 'Toast' - }, - ], - 'Breakfast!' + id='play', + label='Breakfast!', + refresh_url=url_for('ui.list_items', model_name='brand', view='option') ) }} {% endblock %} \ No newline at end of file diff --git a/inventory/ui/blueprint.py b/inventory/ui/blueprint.py index 160f9a5..74b0df9 100644 --- a/inventory/ui/blueprint.py +++ b/inventory/ui/blueprint.py @@ -50,7 +50,9 @@ def list_items(model_name): rows = call(Model, "ui_query", db.session, text=text, limit=limit, offset=offset) \ or default_query(db.session, Model, text=text, limit=limit, offset=offset) + items = [call(Model, 'ui_serialize', r, view=view) or default_serialize(Model, r, view=view) + for r in rows] - data = [ (call(Model, "ui_serialize", r, view=view) or default_serialize(Model, r, view=view)) - for r in rows ] - return jsonify({"items": data}) + if view=="option": + return render_template('fragments/_option_fragment.html', options=items) + return jsonify({"items": items}) diff --git a/inventory/ui/defaults.py b/inventory/ui/defaults.py index 16d8d16..5212156 100644 --- a/inventory/ui/defaults.py +++ b/inventory/ui/defaults.py @@ -89,9 +89,30 @@ def default_delete(session, Model, ids): return count def default_serialize(Model, obj, *, view='option'): - label = infer_label_attr(Model) - data = {'id': obj.id, 'name': getattr(obj, label)} + # 1. Explicit config wins + label_attr = getattr(Model, 'ui_label_attr', None) + + # 2. Otherwise, pick the first PREFERRED_LABELS that exists (can be @property or real column) + if not label_attr: + for candidate in PREFERRED_LABELS: + if hasattr(obj, candidate): + label_attr = candidate + break + + # 3. Fallback to str(obj) if literally nothing found + if not label_attr: + name_val = str(obj) + else: + try: + name_val = getattr(obj, label_attr) + except Exception: + name_val = str(obj) + + data = {'id': obj.id, 'name': name_val} + + # Include extra attrs if defined for attr in getattr(Model, 'ui_extra_attrs', ()): if hasattr(obj, attr): data[attr] = getattr(obj, attr) + return data