adminita 0.1.7__py3-none-any.whl → 0.1.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,28 @@
1
+ {% load i18n %}
2
+
3
+ <div class="filter-group mb-4">
4
+ <details class="group" open>
5
+ <summary class="flex items-center justify-between cursor-pointer py-2 text-sm font-medium text-gray-900 dark:text-white hover:text-blue-600 dark:hover:text-blue-400 transition-colors list-none">
6
+ <span>{{ title }}</span>
7
+ <svg class="w-4 h-4 text-gray-500 transform transition-transform duration-200 group-open:rotate-180" fill="none" stroke="currentColor" viewBox="0 0 24 24">
8
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
9
+ </svg>
10
+ </summary>
11
+ <ul class="mt-2 space-y-1">
12
+ {% for choice in choices %}
13
+ <li>
14
+ {% if choice.selected %}
15
+ <span class="block py-1.5 px-2 text-sm rounded bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 font-medium">
16
+ {{ choice.display }}
17
+ </span>
18
+ {% else %}
19
+ <a href="{{ choice.query_string }}"
20
+ class="block py-1.5 px-2 text-sm rounded text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-gray-900 dark:hover:text-gray-200 transition-colors">
21
+ {{ choice.display }}
22
+ </a>
23
+ {% endif %}
24
+ </li>
25
+ {% endfor %}
26
+ </ul>
27
+ </details>
28
+ </div>
@@ -0,0 +1,79 @@
1
+ {% load adminita_tags %}
2
+ <fieldset class="module aligned {{ fieldset.classes }}{% if not forloop.first %} border-t border-gray-200 dark:border-gray-700{% endif %}">
3
+
4
+ {% if fieldset.name %}
5
+ {# Collapsible Header #}
6
+ <h2 class="fieldset-header flex items-center gap-2 px-6 py-4 bg-gray-50 dark:bg-gray-750 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors"
7
+ onclick="toggleFieldset(this)">
8
+ <svg class="collapse-icon w-4 h-4 text-gray-500 transform transition-transform duration-200 -rotate-90"
9
+ fill="none" stroke="currentColor" viewBox="0 0 24 24">
10
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
11
+ </svg>
12
+ <span class="text-lg font-semibold text-gray-900 dark:text-white">
13
+ {{ fieldset.name }}
14
+ </span>
15
+ </h2>
16
+ {% if fieldset.description %}
17
+ <p class="fieldset-description px-6 pb-2 text-sm text-gray-600 dark:text-gray-400 hidden">
18
+ {{ fieldset.description|safe }}
19
+ </p>
20
+ {% endif %}
21
+ {% endif %}
22
+
23
+ {# Fieldset Content #}
24
+ <div class="fieldset-content px-6 py-6 space-y-6{% if fieldset.name %} hidden{% endif %}">
25
+ {% for line in fieldset %}
26
+ <div class="form-row{% if line.fields|length > 1 %} grid grid-cols-1 md:grid-cols-{{ line.fields|length }} gap-6{% endif %}{% if line.errors %} errors{% endif %}{% if not line.has_visible_field %} hidden{% endif %}">
27
+
28
+ {% if line.fields|length == 1 %}{{ line.errors }}{% endif %}
29
+
30
+ {% for field in line %}
31
+ <div{% if not line.fields|length == 1 %} class="fieldBox{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% if not field.is_readonly and field.errors %} errors{% endif %}"{% endif %}>
32
+
33
+ {% if field.is_checkbox %}
34
+ {# Checkbox fields - label comes after the input #}
35
+ <div class="flex items-center gap-2">
36
+ {{ field.field }}
37
+ {{ field.label_tag }}
38
+ </div>
39
+ {% else %}
40
+ {# Regular fields and readonly fields #}
41
+ {{ field.label_tag }}
42
+
43
+ {% if field.is_readonly %}
44
+ <div class="px-3 py-2 bg-gray-50 dark:bg-gray-750 border border-gray-300 dark:border-gray-600 rounded-lg text-gray-900 dark:text-gray-100">
45
+ {{ field|safe_contents }}
46
+ </div>
47
+ {% else %}
48
+ {{ field.field }}
49
+ {% endif %}
50
+ {% endif %}
51
+
52
+ {# Help text - different access for readonly vs regular fields #}
53
+ {% if field.is_readonly %}
54
+ {% if field.help_text %}
55
+ <p class="mt-2 text-sm text-gray-600 dark:text-gray-400">
56
+ {{ field.help_text|safe }}
57
+ </p>
58
+ {% endif %}
59
+ {% else %}
60
+ {% if field.field.help_text %}
61
+ <p class="mt-2 text-sm text-gray-600 dark:text-gray-400">
62
+ {{ field.field.help_text|safe }}
63
+ </p>
64
+ {% endif %}
65
+ {% endif %}
66
+
67
+ {# Field errors - only for non-readonly fields #}
68
+ {% if not field.is_readonly and field.field.errors %}
69
+ <div class="mt-2 text-sm text-red-600 dark:text-red-400">
70
+ {{ field.field.errors }}
71
+ </div>
72
+ {% endif %}
73
+
74
+ </div>
75
+ {% endfor %}
76
+ </div>
77
+ {% endfor %}
78
+ </div>
79
+ </fieldset>
File without changes
@@ -0,0 +1,53 @@
1
+ """
2
+ Custom template tags for Adminita admin theme.
3
+ Provides Django 6.0 compatibility for readonly field rendering.
4
+ """
5
+
6
+ from django import template
7
+ from django.utils.html import conditional_escape
8
+ from django.utils.safestring import mark_safe
9
+
10
+ register = template.Library()
11
+
12
+
13
+ @register.filter
14
+ def safe_contents(field):
15
+ """
16
+ Safely get the contents of a readonly field.
17
+
18
+ Django 6.0 changed format_html() to require args or kwargs,
19
+ which can cause AdminReadonlyField.contents() to fail for
20
+ certain field types. This filter catches that error and
21
+ provides a fallback.
22
+ """
23
+ try:
24
+ # Try the normal contents() method
25
+ return field.contents()
26
+ except TypeError as e:
27
+ if "args or kwargs must be provided" in str(e):
28
+ # Fallback: try to get the value directly
29
+ try:
30
+ # AdminReadonlyField stores field info in self.field dict
31
+ field_obj = field.field.get("field")
32
+ if callable(field_obj):
33
+ # It's a callable (method on model or modeladmin)
34
+ result = field_obj(field.form.instance)
35
+ else:
36
+ # It's a field name, get value from form instance
37
+ if hasattr(field.form, "instance") and field.form.instance:
38
+ result = getattr(field.form.instance, field_obj, "")
39
+ else:
40
+ result = ""
41
+
42
+ if result is None:
43
+ result = field.empty_value_display
44
+
45
+ return conditional_escape(result)
46
+ except Exception:
47
+ # Last resort: return empty value display
48
+ return field.empty_value_display
49
+ else:
50
+ raise
51
+ except Exception:
52
+ # For any other error, return empty value display
53
+ return getattr(field, "empty_value_display", "-")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: adminita
3
- Version: 0.1.7
3
+ Version: 0.1.9
4
4
  Summary: A modern admin interface for Django using Tailwind CSS v4
5
5
  Author-email: Adminita <hello@todiane.com>
6
6
  License: MIT
@@ -30,7 +30,7 @@ Classifier: Programming Language :: Python :: 3.13
30
30
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
31
31
  Requires-Python: >=3.8
32
32
  Description-Content-Type: text/markdown
33
- License-File: LICENSE
33
+ License-File: LICENSE.md
34
34
  Requires-Dist: Django>=4.0
35
35
  Provides-Extra: dev
36
36
  Requires-Dist: pytest; extra == "dev"
@@ -57,7 +57,7 @@ A modern, beautiful Django admin theme built with Tailwind CSS v4. Transform you
57
57
 
58
58
  - 🎨 **Modern UI** - Clean, professional interface built with Tailwind CSS v4
59
59
  - 🌓 **Dark Mode** - System preference detection with manual toggle
60
- - 📱 **Responsive Design** - Works seamlessly on desktop, tablet, and mobile
60
+ - 📱 **Responsive Design** - Works seamlessly on desktop. Responsive navigation and touch-friendly controls for phones and tablets
61
61
  - 🎯 **Easy Integration** - Drop-in replacement for Django's default admin
62
62
  - ⚡ **Fast** - Optimized CSS with no unnecessary bloat
63
63
  - 🔧 **Customizable** - Easy to customize colors and styling
@@ -70,7 +70,7 @@ A modern, beautiful Django admin theme built with Tailwind CSS v4. Transform you
70
70
  ![adminita light dashboard](https://github.com/djangify/adminita/blob/ac1e111dcf7ffae28dcdca60a78dbf32c848d035/adminita-lightdashboard.png)
71
71
 
72
72
  ### Dark Mode
73
- ![Dark Mode Dashboard - IMAGE COMING SOON - once I fix it!]
73
+ ![Dark Mode Dashboard](https://github.com/djangify/adminita/blob/93e527055807d5e6e05b2fa5724f97835ee53232/adminita-dark-mode.png)
74
74
 
75
75
  ## 🚀 Quick Start
76
76
 
@@ -277,7 +277,38 @@ adminita/
277
277
  ```
278
278
 
279
279
  ## 🐛 Known Issues
280
- None not as of December 2025
280
+
281
+ ## Issue: Search and filters break after zero-result state
282
+
283
+ ### Symptoms
284
+ - Search returns correct results
285
+ - Filters work initially
286
+ - After any action that returns zero results, filters stop working
287
+ - JavaScript error: `undefined is not iterable` in actions.js
288
+
289
+ ### Root cause
290
+ Django's admin/js/actions.js expects specific DOM elements that may not exist
291
+ when the result set is empty, causing a JavaScript crash that breaks subsequent
292
+ page functionality.
293
+
294
+ ### Workaround
295
+ Disable admin actions or add error handling for the zero-result state.
296
+
297
+ ## Known Limitations
298
+ These changes make Adminita usable on mobile, not optimized for mobile:
299
+
300
+ - Complex tables - Very wide tables still require horizontal scrolling
301
+ - Inline formsets - Tabular inlines are cramped; consider using stacked inlines for mobile-heavy use cases
302
+ - Rich text editors - TinyMCE and similar may have their own mobile issues
303
+ - Date/time pickers - Django's default widgets are desktop-focused
304
+
305
+ ## Future Improvements (Community PRs Welcome)
306
+
307
+ - Card-based table view option for mobile (instead of horizontal scroll)
308
+ - Bottom navigation bar for common actions
309
+ - Pull-to-refresh on list pages
310
+ - Improved inline formset mobile layout
311
+ - Native date/time inputs on mobile (<input type="date">)
281
312
 
282
313
  ## 📚 Documentation
283
314
 
@@ -0,0 +1,36 @@
1
+ adminita/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ adminita/apps.py,sha256=8kNa2rgHierXR7asVySUKI46VJu8bmwd9EOivEF42oA,185
3
+ adminita/context_processors.py,sha256=59Q7TyKak3eM924QGjr5EeGOiSZ98YaVCyjTcHS769c,525
4
+ adminita/utils.py,sha256=pUsSfyOsOdpYZ5KACajLLV9GfoWW_TK1ABG3uUJa6g4,2306
5
+ adminita/static/adminita/action-fix.css,sha256=3sCYLHabVTT0CPBHixVhAxDVP29CwTXOBa8ZcqUfxKM,2622
6
+ adminita/static/adminita/adminita-tailwind.css,sha256=Ghg7g9DM5cZMjnwv3AdlGvZf7ovPav9yNk6vLCl5gNw,69351
7
+ adminita/static/adminita/adminita-tailwind.js,sha256=wd6kQZCBJhQk-kCngMmxyiXx51kRQ0PK-STKoYe9xHE,3318
8
+ adminita/static/css/output.css,sha256=f7xqy5Mr0jOJMhFVS_tyke4Iax9I8ypYB9CUJ4zepUU,82912
9
+ adminita/static/src/input.css,sha256=WClzP8fmuonLOe9SyiUHAFnZSmlZG0VgAJ0ye_36iHo,14350
10
+ adminita/templates/admin/actions.html,sha256=cPGheGWYRG4n2LyWJJzZBtyfnlCZyeREFk-y-xcpFU0,831
11
+ adminita/templates/admin/app_index.html,sha256=rPlhwWcDz_6WyszObeVGsCx-xfEwSBzC2iDx6ZO5Hf8,3206
12
+ adminita/templates/admin/base.html,sha256=gMMV_c6Ti10IYG2o6WhxQUlUt8GZJuvueqbXUlUHhRo,11103
13
+ adminita/templates/admin/change_form.html,sha256=EMO69_Q5Lf2TnniKTsySJTE1gmJRsP3WRDWgqUH6Xhg,6190
14
+ adminita/templates/admin/change_list.html,sha256=CCFLktFLoVD0scYC0OND_g7g2F_DkXhYwrITT96pid4,14304
15
+ adminita/templates/admin/change_list_results.html,sha256=f92fMm6l7MaqPz_bZfZHzRoIGsL4iu73ae293BVnqe0,2270
16
+ adminita/templates/admin/delete_confirmation.html,sha256=Mzgi8lZZ1FTn2eZSM8HqK4GhALesQkZu2QTyssLzpPg,5836
17
+ adminita/templates/admin/delete_selected_confirmation.html,sha256=tq0vIJ9eeLADNZSRgxELaE0UK8L0r0vnn6QZqJxieQ4,6051
18
+ adminita/templates/admin/filter.html,sha256=ktzuAtdz1MLJneo2yQgWuV1rLJQ_Hl-rQOI6p3izOv0,1455
19
+ adminita/templates/admin/index.html,sha256=MEYoBvs1WMhMhD8h46DrecAUcW70qcQXmr3Wprin8bg,7009
20
+ adminita/templates/admin/logged_out.html,sha256=rMcFawfTVMUrKr47mKFoSnrd95yUUsN90TG8cJmXlOY,6670
21
+ adminita/templates/admin/login.html,sha256=9HsOKISPrsxVDvdgm9s9oNnz1CZYAHHbjga3sM9ePOs,8453
22
+ adminita/templates/admin/object_history.html,sha256=t01XSu9xqeGIs8QZNtZav6jchyH1_8dmz9VTG-0HONE,6718
23
+ adminita/templates/admin/password_change_done.html,sha256=_n0CtRSyi5J-E7wsTZqn4u7URs1eL294D6ipo5MpWVI,1831
24
+ adminita/templates/admin/password_change_form.html,sha256=fw58OLBteChy7r0DRbCiFTsk7Twa5fz1FAiFxZ9DH5c,7304
25
+ adminita/templates/admin/popup_response.html,sha256=GJtE8squ1qpcgZkeMjHgkSQDv5rXTV1SWSQR58AFZII,924
26
+ adminita/templates/admin/submit_line.html,sha256=nyM06xhlT0lGaOK8nYfqjfNu_52Kk7J-LH0d63ThiLc,1513
27
+ adminita/templates/admin/edit_inline/stacked.html,sha256=dWpeHLPg1eCnmW795oWORvshO1v4-E5azc0lwX0td04,5583
28
+ adminita/templates/admin/edit_inline/tabular.html,sha256=K43Vl9FMiAMWBf5jSrD33BGLeLuq2dGmLmxiKAce3o4,6563
29
+ adminita/templates/admin/includes/fieldset.html,sha256=qAAZlF3PT5CHG1MLYEF9NuO3l6hLFet0EBAyPHmGZnY,3816
30
+ adminita/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
+ adminita/templatetags/adminita_tags.py,sha256=_poeY9DzEOvDy2muVXZeNItH3NtyeGXi4MFpi_-FsI0,1944
32
+ adminita-0.1.9.dist-info/licenses/LICENSE.md,sha256=pH2s9_dYGXbt81EPn0RTenMzlMmgH65KfQhnUuENiT0,1131
33
+ adminita-0.1.9.dist-info/METADATA,sha256=fJGit7Lz7MiQwM9DbJH94EF0rWqoJj3J5jh_MuuiMMQ,13089
34
+ adminita-0.1.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
35
+ adminita-0.1.9.dist-info/top_level.txt,sha256=bHXkKMEo8dBqliVV347K_MWJG-dyuNzj9cwXYg6gEa8,9
36
+ adminita-0.1.9.dist-info/RECORD,,
@@ -1,29 +0,0 @@
1
- adminita/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- adminita/apps.py,sha256=8kNa2rgHierXR7asVySUKI46VJu8bmwd9EOivEF42oA,185
3
- adminita/context_processors.py,sha256=59Q7TyKak3eM924QGjr5EeGOiSZ98YaVCyjTcHS769c,525
4
- adminita/utils.py,sha256=pUsSfyOsOdpYZ5KACajLLV9GfoWW_TK1ABG3uUJa6g4,2306
5
- adminita/static/adminita/adminita-tailwind.css,sha256=zJhQZAxgtvgW4_9ppUcnH1H_uHxPnqduO6B_ZPkRtHw,65741
6
- adminita/static/adminita/adminita-tailwind.js,sha256=wd6kQZCBJhQk-kCngMmxyiXx51kRQ0PK-STKoYe9xHE,3318
7
- adminita/static/css/output.css,sha256=f7xqy5Mr0jOJMhFVS_tyke4Iax9I8ypYB9CUJ4zepUU,82912
8
- adminita/static/src/input.css,sha256=O7FnaNH3ouRU-y8XwLcU7ORjKkKyxIDiKEZGslXuRnY,13191
9
- adminita/templates/admin/app_index.html,sha256=rPlhwWcDz_6WyszObeVGsCx-xfEwSBzC2iDx6ZO5Hf8,3206
10
- adminita/templates/admin/base.html,sha256=t5jujpmoB1NxGbvLCPcTnz9TTpgB-OYLxcv-_IQnb3c,11028
11
- adminita/templates/admin/change_form.html,sha256=EE0ZXt1agxRrCwnjhZjv2V8KbN1x6TIXvm7SZzIUdGU,9450
12
- adminita/templates/admin/change_list.html,sha256=gsUCYOBtp6QLxfRSuFtuE5rIAkke0UPEjMghLHLHfaQ,9743
13
- adminita/templates/admin/delete_confirmation.html,sha256=Mzgi8lZZ1FTn2eZSM8HqK4GhALesQkZu2QTyssLzpPg,5836
14
- adminita/templates/admin/delete_selected_confirmation.html,sha256=tq0vIJ9eeLADNZSRgxELaE0UK8L0r0vnn6QZqJxieQ4,6051
15
- adminita/templates/admin/index.html,sha256=MEYoBvs1WMhMhD8h46DrecAUcW70qcQXmr3Wprin8bg,7009
16
- adminita/templates/admin/logged_out.html,sha256=rMcFawfTVMUrKr47mKFoSnrd95yUUsN90TG8cJmXlOY,6670
17
- adminita/templates/admin/login.html,sha256=9HsOKISPrsxVDvdgm9s9oNnz1CZYAHHbjga3sM9ePOs,8453
18
- adminita/templates/admin/object_history.html,sha256=t01XSu9xqeGIs8QZNtZav6jchyH1_8dmz9VTG-0HONE,6718
19
- adminita/templates/admin/password_change_done.html,sha256=_n0CtRSyi5J-E7wsTZqn4u7URs1eL294D6ipo5MpWVI,1831
20
- adminita/templates/admin/password_change_form.html,sha256=fw58OLBteChy7r0DRbCiFTsk7Twa5fz1FAiFxZ9DH5c,7304
21
- adminita/templates/admin/popup_response.html,sha256=GJtE8squ1qpcgZkeMjHgkSQDv5rXTV1SWSQR58AFZII,924
22
- adminita/templates/admin/submit_line.html,sha256=nyM06xhlT0lGaOK8nYfqjfNu_52Kk7J-LH0d63ThiLc,1513
23
- adminita/templates/admin/edit_inline/stacked.html,sha256=oItxAp76TVdB5NmR1Bf1WlbjA0WNttlGk-ntbt-jCaI,5580
24
- adminita/templates/admin/edit_inline/tabular.html,sha256=fAuSecCg5p64zC80uuW6oLzdM1a58VjwFSOtnc3F7yg,7767
25
- adminita-0.1.7.dist-info/licenses/LICENSE,sha256=pH2s9_dYGXbt81EPn0RTenMzlMmgH65KfQhnUuENiT0,1131
26
- adminita-0.1.7.dist-info/METADATA,sha256=mWqqBHXEtMTL9K1yq9JKk8rRcznG2fNJo_0_qwC4VN0,11701
27
- adminita-0.1.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
- adminita-0.1.7.dist-info/top_level.txt,sha256=bHXkKMEo8dBqliVV347K_MWJG-dyuNzj9cwXYg6gEa8,9
29
- adminita-0.1.7.dist-info/RECORD,,