Skip to content

Commit

Permalink
Support help texts for fields
Browse files Browse the repository at this point in the history
Also improves formatting for deeply nested data.
  • Loading branch information
matti-lamppu committed Dec 7, 2022
1 parent 8c37e85 commit 5629121
Show file tree
Hide file tree
Showing 11 changed files with 466 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,63 @@
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}">
<style>
@media (min-width: 895px) {
.adv-dict-label {
float: none!important;
}
}

div.adv-dict,
div.adv-dict,
div.adv-array {
display: flow-root;
}

div.adv-array > ul {
display: inline-table;
margin-top: 0;
padding-top: 0;
}

div.adv-array > ul > li {
margin-top: 0;
padding-top: 0;
}

div.adv-data label {
display: inline-flex;
max-width: 150px;
min-width: 100px;
line-height: normal;
margin: 2px 0 2px 0!important;
padding: 0.5rem 0 0 0!important;
float: left;
}

div.adv-data input,
div.adv-data textarea {
width: 20em;
margin: 4px 0 4px 0!important;
display: inline-flex;
align-items: center;
}

div.adv-array > ul > li> div.adv-array-item,
div.adv-dict > div.adv-dict-items > div.adv-dict-item {
display: inline-flex;
}

div.adv-dict > div.adv-dict-items,
div.adv-item {
display: inline-block;
}

div.adv-data div.help {
margin-left: 0!important;
padding-left: 0!important;
}

@media (max-width: 1024px) {
div.adv-data label {
padding: 0.75rem 0 0 0!important;
}
}

</style>
{% endblock %}

Expand All @@ -33,33 +85,33 @@
{% block content %}
<div id="content-main">
<form method="post" novalidate>{% csrf_token %}
<div>
<div class="adv-data">
{% if image %}
<img src="{{ image }}" alt="" style="max-width: 470px; padding-bottom: 10px">
{% endif %}
{% for section in data %}
<fieldset class="module aligned">
{% if section.name %}
<h2>{{ section.name }}</h2>
<h2>{{ section.name }}</h2>
{% endif %}
{% if section.description %}
<div class="description">{{ section.description|safe }}</div>
<div class="description">{{ section.description|safe }}</div>
{% endif %}
{% for key, value in section.fields.items %}
<div class="form-row">
{% if value|get_type == "dict" %}
{% include 'admin_data_views/dict_item.html' with label=key items=value only %}
{% elif value|get_type == "list" %}
{% include 'admin_data_views/list_item.html' with label=key items=value only %}
{% else %}
<div class="fieldBox">
<label class="required">{{ key|capfirst }}</label>
{% include 'admin_data_views/item.html' with value=value only %}
</div>
{% endif %}
<br>
<div class="adv-dict-items">
{% for key, value in section|fields_with_help_texts|items %}
<div class="form-row adv-dict-item">
{% if value.0|get_type == "dict" %}
{% include 'admin_data_views/dict_item.html' with label=key items=value only %}
{% elif value.0|get_type == "list" %}
{% include 'admin_data_views/list_item.html' with label=key items=value only %}
{% else %}
<label class="required">{{ key|capfirst }}</label>
{% include 'admin_data_views/item.html' with value=value only %}
{% endif %}
<br>
</div>
{% endfor %}
</div>
{% endfor %}
</fieldset>
{% endfor %}
</div>
Expand Down
40 changes: 23 additions & 17 deletions admin_data_views/templates/admin_data_views/dict_item.html
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
{% load i18n static admin_data_utils %}

{% if label != "" %}
<label class="required adv-dict-label">{{ label|capfirst }}</label>
{% endif %}
<div class="adv-dict">
{% if label != "" %}
<label class="required">{{ label|capfirst }}</label>
{% endif %}

<div style="float: left;">
{% for key, value in items.items %}
{% if value|get_type == "dict" %}
{% include 'admin_data_views/dict_item.html' with label=key items=value only %}
{% elif value|get_type == "list" %}
{% include 'admin_data_views/list_item.html' with label=key items=value only %}
{% else %}
<div class="fieldBox" style="float: none">
<label class="required" style="float: none;display: inline-block">{{ key|capfirst }}</label>
{% include 'admin_data_views/item.html' with value=value only %}
</div>
{% endif %}
<br>
{% endfor %}
<div class="adv-dict-items">
{% for key, value in items.0.items %}
<div class="adv-dict-item">
{% if value.0|get_type == "dict" %}
{% include 'admin_data_views/dict_item.html' with label=key items=value only %}
{% elif value.0|get_type == "list" %}
{% include 'admin_data_views/list_item.html' with label=key items=value only %}
{% else %}
<label class="required">{{ key|capfirst }}</label>
{% include 'admin_data_views/item.html' with value=value only %}
{% endif %}
</div>
<br>
{% endfor %}
</div>

{% if items.1 %}
<div class="help">{{ items.1|safe }}</div>
{% endif %}
</div>
16 changes: 11 additions & 5 deletions admin_data_views/templates/admin_data_views/item.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
{% if value|length > 40 %}
<textarea type="text" rows="6" class="vTextField" disabled>{{ value|safe }}</textarea>
{% else %}
<input type="text" value="{{ value|safe }}" class="vTextField" disabled>
{% endif %}
<div class="adv-item">
{% if value.0|length > 40 %}
<textarea type="text" rows="6" disabled>{{ value.0|safe }}</textarea>
{% else %}
<input type="text" value="{{ value.0|safe }}" disabled>
{% endif %}

{% if value.1 %}
<div class="help">{{ value.1|safe }}</div>
{% endif %}
</div>
44 changes: 27 additions & 17 deletions admin_data_views/templates/admin_data_views/list_item.html
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
{% load i18n static admin_data_utils %}

{% if label != "" %}
<label class="required">{{ label|capfirst }}</label>
{% endif %}

<div style="float: left;">
{% for value in items %}
{% if value|get_type == "dict" %}
{% include 'admin_data_views/dict_item.html' with label="" items=value only %}
{% elif value|get_type == "list" %}
{% include 'admin_data_views/list_item.html' with label="" items=value only %}
{% else %}
<div class="fieldBox">
{% include 'admin_data_views/item.html' with value=value only %}
</div>
<div class="related-widget-wrapper">
<div class="adv-array">
{% if label != "" %}
<label class="required">{{ label|capfirst }}</label>
{% endif %}
<hr>
<br>
{% endfor %}

<ul>
{% for value in items.0 %}
<li>
<div class="adv-array-item">
{% if value.0|get_type == "dict" %}
{% include 'admin_data_views/dict_item.html' with label="" items=value only %}
{% elif value.0|get_type == "list" %}
{% include 'admin_data_views/list_item.html' with label="" items=value only %}
{% else %}
{% include 'admin_data_views/item.html' with value=value only %}
{% endif %}
</div>
<hr style="margin: 3px 0">
</li>
{% endfor %}

{% if items.1 %}
<div class="help">{{ items.1|safe }}</div>
{% endif %}

</ul>
</div>
</div>
46 changes: 45 additions & 1 deletion admin_data_views/templatetags/admin_data_utils.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,53 @@
from django import template

from ..typing import Any, Dict, DictItems, ItemsView, NestedDict, SectionData, Union


register = template.Library()


@register.filter
def get_type(value) -> str:
def get_type(value: Any) -> str:
"""Get item type as a string."""
return type(value).__name__


@register.filter
def items(value: Dict[str, Any]) -> ItemsView[str, Any]:
"""Get dict items."""
return value.items()


@register.filter
def fields_with_help_texts(section_data: SectionData) -> Dict[str, DictItems]:
"""Add help texts and iterate as dict items."""

def add_help_text(fields: NestedDict, help_texts: NestedDict) -> Dict[str, DictItems]:
formatted_fields: Dict[str, DictItems] = {}

for key, value in fields.items():
help_text: Union[str, NestedDict] = help_texts.get(key, "")

if isinstance(value, dict):
if isinstance(help_text, str):
formatted_fields[key] = (add_help_text(value, {}), help_text)
else:
formatted_fields[key] = (add_help_text(value, help_text), "")
elif isinstance(value, list):
values = []
for item in value:
if not isinstance(item, (dict, list)):
values.append((item, ""))
else:
res = add_help_text(item, {} if isinstance(help_text, str) else help_text)
if not isinstance(res, tuple):
res = (res, "")
values.append(res)

formatted_fields[key] = (values, help_text if isinstance(help_text, str) else "")
else:
formatted_fields[key] = (value, help_text)

return formatted_fields

return add_help_text(section_data["fields"], section_data.get("help_texts", {}))
21 changes: 18 additions & 3 deletions admin_data_views/typing.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Callable, Dict, List, NamedTuple, Optional, Set, TypedDict, Union
from typing import Any, Callable, Dict, ItemsView, List, NamedTuple, Optional, Set, Tuple, TypedDict, Union


__all__ = [
Expand All @@ -7,19 +7,30 @@
"AppModel",
"Callable",
"Dict",
"DictItems",
"ItemContext",
"ItemsView",
"ItemViewContext",
"List",
"NamedTuple",
"NestedDict",
"Optional",
"SectionData",
"Set",
"TableContext",
"TableViewContext",
"Tuple",
"Union",
"URLConfig",
]


NestedDict = Dict[str, Union[str, "NestedDict"]]
NestedItem = List[Union[str, NestedDict, "NestedItem"]]
DictItem = Union[str, NestedDict, NestedItem]
DictItems = Tuple[DictItem, str]


class Perms(TypedDict):
add: bool
change: bool
Expand Down Expand Up @@ -63,10 +74,14 @@ class TableViewContext(TypedDict):
rows: List[List[Any]]


class SectionData(TypedDict):
class SectionDataBase(TypedDict):
name: Optional[str]
description: Optional[str]
fields: Dict[str, Any]
fields: NestedDict


class SectionData(SectionDataBase, total=False):
help_texts: NestedDict


class ItemContextBase(TypedDict):
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "django-admin-data-views"
version = "0.2.6"
version = "0.3.0"
description = "Add custom data views to django admin panel."
authors = [
"Matti Lamppu <[email protected]>",
Expand Down
5 changes: 5 additions & 0 deletions tests/django/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,5 +135,10 @@
"view": "tests.django.urls.buzz_view",
"name": "buzz",
},
{
"route": "complex/",
"view": "tests.django.urls.complex_view",
"name": "complex",
},
],
}
Loading

0 comments on commit 5629121

Please sign in to comment.