django-admin-mobile 0.2.4__tar.gz → 0.2.6__tar.gz

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.
Files changed (172) hide show
  1. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/CHANGELOG.md +11 -0
  2. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/PKG-INFO +3 -3
  3. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/README.md +2 -2
  4. django_admin_mobile-0.2.6/docs/screenshots/app-index-375-dark.png +0 -0
  5. django_admin_mobile-0.2.6/docs/screenshots/app-index-375.png +0 -0
  6. django_admin_mobile-0.2.6/docs/screenshots/bulk-375-dark.png +0 -0
  7. django_admin_mobile-0.2.6/docs/screenshots/bulk-375.png +0 -0
  8. django_admin_mobile-0.2.6/docs/screenshots/changelist-375-dark.png +0 -0
  9. django_admin_mobile-0.2.6/docs/screenshots/changelist-375.png +0 -0
  10. django_admin_mobile-0.2.6/docs/screenshots/changelist-editable-375-dark.png +0 -0
  11. django_admin_mobile-0.2.6/docs/screenshots/changelist-editable-375.png +0 -0
  12. django_admin_mobile-0.2.6/docs/screenshots/favorites-375-dark.png +0 -0
  13. django_admin_mobile-0.2.6/docs/screenshots/favorites-375.png +0 -0
  14. django_admin_mobile-0.2.6/docs/screenshots/history-375-dark.png +0 -0
  15. django_admin_mobile-0.2.6/docs/screenshots/history-375.png +0 -0
  16. django_admin_mobile-0.2.6/docs/screenshots/infinite-scroll-375-dark.png +0 -0
  17. django_admin_mobile-0.2.6/docs/screenshots/infinite-scroll-375.png +0 -0
  18. django_admin_mobile-0.2.6/docs/screenshots/message-375-dark.png +0 -0
  19. django_admin_mobile-0.2.6/docs/screenshots/message-375.png +0 -0
  20. django_admin_mobile-0.2.6/docs/screenshots/nav-sidebar-375-dark.png +0 -0
  21. django_admin_mobile-0.2.6/docs/screenshots/nav-sidebar-375.png +0 -0
  22. django_admin_mobile-0.2.6/docs/screenshots/payments-375-dark.png +0 -0
  23. django_admin_mobile-0.2.6/docs/screenshots/payments-375.png +0 -0
  24. django_admin_mobile-0.2.6/docs/screenshots/payments-selected-375-dark.png +0 -0
  25. django_admin_mobile-0.2.6/docs/screenshots/payments-selected-375.png +0 -0
  26. django_admin_mobile-0.2.6/docs/screenshots/pull-375-dark.png +0 -0
  27. django_admin_mobile-0.2.6/docs/screenshots/pull-375.png +0 -0
  28. django_admin_mobile-0.2.6/docs/screenshots/rtl-changelist-375-dark.png +0 -0
  29. django_admin_mobile-0.2.6/docs/screenshots/rtl-changelist-375.png +0 -0
  30. django_admin_mobile-0.2.6/docs/screenshots/swipe-375-dark.png +0 -0
  31. django_admin_mobile-0.2.6/docs/screenshots/swipe-375.png +0 -0
  32. django_admin_mobile-0.2.6/docs/screenshots/toast-375-dark.png +0 -0
  33. django_admin_mobile-0.2.6/docs/screenshots/toast-375.png +0 -0
  34. django_admin_mobile-0.2.6/docs/screenshots/undo-375-dark.png +0 -0
  35. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/example/library/admin.py +43 -0
  36. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/example/library/demo.py +12 -0
  37. django_admin_mobile-0.2.6/example/library/migrations/0004_payment.py +96 -0
  38. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/example/library/models.py +32 -0
  39. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/__init__.py +1 -1
  40. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/static/admin_mobile/css/admin_mobile.css +14 -6
  41. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/static/admin_mobile/css/admin_mobile_features.css +171 -17
  42. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/static/admin_mobile/js/admin_mobile.js +16 -0
  43. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/static/admin_mobile/js/admin_mobile_features.js +38 -9
  44. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/tests/test_playwright.py +80 -0
  45. django_admin_mobile-0.2.4/docs/screenshots/app-index-375-dark.png +0 -0
  46. django_admin_mobile-0.2.4/docs/screenshots/app-index-375.png +0 -0
  47. django_admin_mobile-0.2.4/docs/screenshots/bulk-375-dark.png +0 -0
  48. django_admin_mobile-0.2.4/docs/screenshots/bulk-375.png +0 -0
  49. django_admin_mobile-0.2.4/docs/screenshots/changelist-375-dark.png +0 -0
  50. django_admin_mobile-0.2.4/docs/screenshots/changelist-375.png +0 -0
  51. django_admin_mobile-0.2.4/docs/screenshots/changelist-editable-375-dark.png +0 -0
  52. django_admin_mobile-0.2.4/docs/screenshots/changelist-editable-375.png +0 -0
  53. django_admin_mobile-0.2.4/docs/screenshots/favorites-375-dark.png +0 -0
  54. django_admin_mobile-0.2.4/docs/screenshots/favorites-375.png +0 -0
  55. django_admin_mobile-0.2.4/docs/screenshots/history-375-dark.png +0 -0
  56. django_admin_mobile-0.2.4/docs/screenshots/history-375.png +0 -0
  57. django_admin_mobile-0.2.4/docs/screenshots/infinite-scroll-375-dark.png +0 -0
  58. django_admin_mobile-0.2.4/docs/screenshots/infinite-scroll-375.png +0 -0
  59. django_admin_mobile-0.2.4/docs/screenshots/message-375-dark.png +0 -0
  60. django_admin_mobile-0.2.4/docs/screenshots/message-375.png +0 -0
  61. django_admin_mobile-0.2.4/docs/screenshots/nav-sidebar-375-dark.png +0 -0
  62. django_admin_mobile-0.2.4/docs/screenshots/nav-sidebar-375.png +0 -0
  63. django_admin_mobile-0.2.4/docs/screenshots/pull-375-dark.png +0 -0
  64. django_admin_mobile-0.2.4/docs/screenshots/pull-375.png +0 -0
  65. django_admin_mobile-0.2.4/docs/screenshots/rtl-changelist-375-dark.png +0 -0
  66. django_admin_mobile-0.2.4/docs/screenshots/rtl-changelist-375.png +0 -0
  67. django_admin_mobile-0.2.4/docs/screenshots/swipe-375-dark.png +0 -0
  68. django_admin_mobile-0.2.4/docs/screenshots/swipe-375.png +0 -0
  69. django_admin_mobile-0.2.4/docs/screenshots/toast-375-dark.png +0 -0
  70. django_admin_mobile-0.2.4/docs/screenshots/toast-375.png +0 -0
  71. django_admin_mobile-0.2.4/docs/screenshots/undo-375-dark.png +0 -0
  72. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/.gitignore +0 -0
  73. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/CONTRIBUTING.md +0 -0
  74. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/LICENSE +0 -0
  75. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/admindocs-375-dark.png +0 -0
  76. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/admindocs-375.png +0 -0
  77. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/admindocs-model-375-dark.png +0 -0
  78. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/admindocs-model-375.png +0 -0
  79. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/calendar-375-dark.png +0 -0
  80. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/calendar-375.png +0 -0
  81. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/camera-375-dark.png +0 -0
  82. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/camera-375.png +0 -0
  83. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/change-form-375-dark.png +0 -0
  84. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/change-form-375.png +0 -0
  85. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/clock-375-dark.png +0 -0
  86. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/clock-375.png +0 -0
  87. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/delete-confirm-375-dark.png +0 -0
  88. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/delete-confirm-375.png +0 -0
  89. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/edition-375-dark.png +0 -0
  90. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/edition-375.png +0 -0
  91. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/filters-375-dark.png +0 -0
  92. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/filters-375.png +0 -0
  93. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/index-375-dark.png +0 -0
  94. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/index-375.png +0 -0
  95. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/inline-errors-375-dark.png +0 -0
  96. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/inline-errors-375.png +0 -0
  97. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/lightbox-375-dark.png +0 -0
  98. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/lightbox-375.png +0 -0
  99. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/logged-out-375-dark.png +0 -0
  100. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/logged-out-375.png +0 -0
  101. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/login-375-dark.png +0 -0
  102. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/login-375.png +0 -0
  103. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/navigator-375-dark.png +0 -0
  104. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/navigator-375.png +0 -0
  105. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/password-change-375-dark.png +0 -0
  106. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/password-change-375.png +0 -0
  107. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/picker-375-dark.png +0 -0
  108. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/picker-375.png +0 -0
  109. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/popup-375-dark.png +0 -0
  110. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/popup-375.png +0 -0
  111. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/readonly-375-dark.png +0 -0
  112. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/readonly-375.png +0 -0
  113. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/recent-375-dark.png +0 -0
  114. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/recent-375.png +0 -0
  115. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/search-375-dark.png +0 -0
  116. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/search-375.png +0 -0
  117. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/slide-confirm-375-dark.png +0 -0
  118. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/slide-confirm-375.png +0 -0
  119. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/tabs-375-dark.png +0 -0
  120. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/tabs-375.png +0 -0
  121. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/docs/screenshots/undo-375.png +0 -0
  122. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/example/example/__init__.py +0 -0
  123. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/example/example/settings.py +0 -0
  124. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/example/example/urls.py +0 -0
  125. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/example/example/wsgi.py +0 -0
  126. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/example/library/__init__.py +0 -0
  127. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/example/library/apps.py +0 -0
  128. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/example/library/management/__init__.py +0 -0
  129. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/example/library/management/commands/__init__.py +0 -0
  130. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/example/library/management/commands/seed_demo.py +0 -0
  131. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/example/library/migrations/0001_initial.py +0 -0
  132. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/example/library/migrations/0002_admin_surfaces.py +0 -0
  133. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/example/library/migrations/0003_shelf_plural.py +0 -0
  134. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/example/library/migrations/__init__.py +0 -0
  135. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/example/manage.py +0 -0
  136. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/pyproject.toml +0 -0
  137. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/apps.py +0 -0
  138. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/checks.py +0 -0
  139. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/colors.py +0 -0
  140. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/conf.py +0 -0
  141. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/mixins.py +0 -0
  142. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/overrides.py +0 -0
  143. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/py.typed +0 -0
  144. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/readonly.py +0 -0
  145. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/routing.py +0 -0
  146. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/search.py +0 -0
  147. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/static/admin_mobile/icons/icon-192.png +0 -0
  148. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/static/admin_mobile/icons/icon-512.png +0 -0
  149. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/templates/admin/admin_mobile/recent.html +0 -0
  150. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/templates/admin/admin_mobile/search.html +0 -0
  151. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/templates/admin/base.html +0 -0
  152. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/templates/admin/change_list.html +0 -0
  153. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/templates/admin_mobile/widgets/split_datetime.html +0 -0
  154. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/templatetags/__init__.py +0 -0
  155. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/templatetags/admin_mobile.py +0 -0
  156. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/views.py +0 -0
  157. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/src/admin_mobile/widgets.py +0 -0
  158. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/tests/__init__.py +0 -0
  159. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/tests/formparse.py +0 -0
  160. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/tests/settings.py +0 -0
  161. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/tests/test_admin_save.py +0 -0
  162. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/tests/test_checks.py +0 -0
  163. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/tests/test_config.py +0 -0
  164. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/tests/test_demo.py +0 -0
  165. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/tests/test_features.py +0 -0
  166. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/tests/test_formparse.py +0 -0
  167. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/tests/test_mixin.py +0 -0
  168. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/tests/test_static_contract.py +0 -0
  169. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/tests/test_templates.py +0 -0
  170. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/tests/test_widgets.py +0 -0
  171. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/tests/urls.py +0 -0
  172. {django_admin_mobile-0.2.4 → django_admin_mobile-0.2.6}/tox.ini +0 -0
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.6
4
+
5
+ - “Save this list” is a full-width 44px control on the same 16px edge as the rest of the changelist.
6
+ - While the sticky bulk bar is open, the top action menu and Run are hidden. Select all and the count stay. With JavaScript off, that top row stays in place.
7
+
8
+ ## 0.2.5
9
+
10
+ - A selected changelist card uses a light accent tint and outline instead of Django’s flat selected-row fill.
11
+ - The checkbox and the linked column share one left-aligned title line. Field labels stay on the rows below, about 40% wide, with values wrapping in the rest of the row.
12
+ - Rich cell HTML and list-editable inputs stay inside the value column. The sticky bulk bar is full width above the tab bar: the count, the action menu, and Run share one row.
13
+
3
14
  ## 0.2.4
4
15
 
5
16
  - The action menu and Run share one 44px row and the same corner radius. Run stays only as wide as its label.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: django-admin-mobile
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: Make the native Django admin usable on phones without replacing its look.
5
5
  Project-URL: Homepage, https://github.com/daniilshamraev/django-admin-mobile
6
6
  Project-URL: Repository, https://github.com/daniilshamraev/django-admin-mobile
@@ -207,9 +207,9 @@ uv run tox
207
207
 
208
208
  ## Publishing
209
209
 
210
- 0.1.0 is already on PyPI. This tree is 0.2.4 and is not published from here.
210
+ 0.1.0 is already on PyPI. This tree is 0.2.6 and is not published from here.
211
211
 
212
- 1. Tag `0.2.4` when you want a release.
212
+ 1. Tag `0.2.6` when you want a release.
213
213
  2. Build: `uv build`.
214
214
  3. Publish: `uv publish` with a PyPI token.
215
215
 
@@ -167,9 +167,9 @@ uv run tox
167
167
 
168
168
  ## Publishing
169
169
 
170
- 0.1.0 is already on PyPI. This tree is 0.2.4 and is not published from here.
170
+ 0.1.0 is already on PyPI. This tree is 0.2.6 and is not published from here.
171
171
 
172
- 1. Tag `0.2.4` when you want a release.
172
+ 1. Tag `0.2.6` when you want a release.
173
173
  2. Build: `uv build`.
174
174
  3. Publish: `uv publish` with a PyPI token.
175
175
 
@@ -1,6 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from django.contrib import admin
4
+ from django.templatetags.static import static
5
+ from django.utils.html import format_html
4
6
 
5
7
  from admin_mobile.mixins import MobileAdminMixin
6
8
  from library.models import (
@@ -10,6 +12,7 @@ from library.models import (
10
12
  Chapter,
11
13
  Citation,
12
14
  Edition,
15
+ Payment,
13
16
  Publisher,
14
17
  Revision,
15
18
  Series,
@@ -142,6 +145,46 @@ class RevisionAdmin(admin.ModelAdmin):
142
145
  search_fields = ("label",)
143
146
 
144
147
 
148
+ @admin.action(description="Отметить проверенным")
149
+ def mark_reviewed(
150
+ modeladmin: admin.ModelAdmin, request: object, queryset: object
151
+ ) -> None:
152
+ del modeladmin, request
153
+ queryset.update(reviewed=True)
154
+
155
+
156
+ @admin.register(Payment)
157
+ class PaymentAdmin(MobileAdminMixin, admin.ModelAdmin):
158
+ """No card-title hint: the link column itself has to become the title."""
159
+
160
+ list_display = (
161
+ "id",
162
+ "payer",
163
+ "amount",
164
+ "system",
165
+ "status",
166
+ "paid_on",
167
+ "external_id",
168
+ "comment",
169
+ "currency",
170
+ )
171
+ list_display_links = ("id",)
172
+ list_editable = ("amount",)
173
+ list_per_page = 10
174
+ actions = (mark_reviewed,)
175
+
176
+ @admin.display(description="Пользователь")
177
+ def payer(self, obj: Payment) -> str:
178
+ return format_html(
179
+ '<img alt="" src="{}" width="16" height="16"> <strong>{}</strong> '
180
+ '(<a href="https://vk.com/id{}">vk.com/id{}</a>)',
181
+ static("admin/img/icon-viewlink.svg"),
182
+ obj.payer_name,
183
+ obj.vk_id,
184
+ obj.vk_id,
185
+ )
186
+
187
+
145
188
  @admin.register(Appointment)
146
189
  class AppointmentAdmin(admin.ModelAdmin):
147
190
  """Stock widgets on purpose, so the admin calendar and clock remain."""
@@ -26,6 +26,7 @@ def seed_demo(*args: object, **kwargs: object) -> bool:
26
26
  Chapter,
27
27
  Citation,
28
28
  Edition,
29
+ Payment,
29
30
  Publisher,
30
31
  Revision,
31
32
  Series,
@@ -140,4 +141,15 @@ def seed_demo(*args: object, **kwargs: object) -> bool:
140
141
  at_time=time(18, 30),
141
142
  when=timezone.make_aware(datetime(2026, 4, 2, 18, 30)),
142
143
  )
144
+ Payment.objects.create(
145
+ payer_name="Мария Александровна Волконская",
146
+ vk_id="123456789012345678",
147
+ amount="1490.50",
148
+ system=Payment.System.WALLET,
149
+ status="Оплачен",
150
+ paid_on=date(2026, 3, 2),
151
+ external_id="pay-1843-notes",
152
+ comment="Перевод за второе издание",
153
+ currency="RUB",
154
+ )
143
155
  return True
@@ -0,0 +1,96 @@
1
+ from django.db import migrations, models
2
+
3
+
4
+ class Migration(migrations.Migration):
5
+ dependencies = [
6
+ ("library", "0003_shelf_plural"),
7
+ ]
8
+
9
+ operations = [
10
+ migrations.CreateModel(
11
+ name="Payment",
12
+ fields=[
13
+ (
14
+ "id",
15
+ models.BigAutoField(
16
+ auto_created=True,
17
+ primary_key=True,
18
+ serialize=False,
19
+ verbose_name="ID",
20
+ ),
21
+ ),
22
+ (
23
+ "payer_name",
24
+ models.CharField(max_length=200, verbose_name="Имя плательщика"),
25
+ ),
26
+ ("vk_id", models.CharField(max_length=64, verbose_name="Профиль")),
27
+ (
28
+ "amount",
29
+ models.DecimalField(
30
+ decimal_places=2,
31
+ max_digits=12,
32
+ verbose_name="Цена в рублях",
33
+ ),
34
+ ),
35
+ (
36
+ "system",
37
+ models.CharField(
38
+ choices=[
39
+ ("card", "Банковская карта"),
40
+ ("wallet", "Электронный кошелёк"),
41
+ ],
42
+ default="card",
43
+ max_length=20,
44
+ verbose_name="Платежная система",
45
+ ),
46
+ ),
47
+ (
48
+ "status",
49
+ models.CharField(
50
+ default="Ожидает",
51
+ max_length=40,
52
+ verbose_name="Статус платежа",
53
+ ),
54
+ ),
55
+ (
56
+ "paid_on",
57
+ models.DateField(
58
+ blank=True, null=True, verbose_name="Дата оплаты"
59
+ ),
60
+ ),
61
+ (
62
+ "external_id",
63
+ models.CharField(
64
+ blank=True,
65
+ max_length=80,
66
+ verbose_name="Внешний идентификатор",
67
+ ),
68
+ ),
69
+ (
70
+ "comment",
71
+ models.CharField(
72
+ blank=True,
73
+ max_length=200,
74
+ verbose_name="Комментарий кассира",
75
+ ),
76
+ ),
77
+ (
78
+ "currency",
79
+ models.CharField(
80
+ default="RUB",
81
+ max_length=12,
82
+ verbose_name="Валюта расчёта",
83
+ ),
84
+ ),
85
+ (
86
+ "reviewed",
87
+ models.BooleanField(default=False, verbose_name="Проверен"),
88
+ ),
89
+ ],
90
+ options={
91
+ "verbose_name": "Платёж",
92
+ "verbose_name_plural": "Платежи",
93
+ "ordering": ["-id"],
94
+ },
95
+ ),
96
+ ]
@@ -160,6 +160,38 @@ class Revision(models.Model):
160
160
  return self.label
161
161
 
162
162
 
163
+ class Payment(models.Model):
164
+ """Long Russian labels, rich HTML, and an editable price."""
165
+
166
+ class System(models.TextChoices):
167
+ CARD = "card", "Банковская карта"
168
+ WALLET = "wallet", "Электронный кошелёк"
169
+
170
+ payer_name = models.CharField("Имя плательщика", max_length=200)
171
+ vk_id = models.CharField("Профиль", max_length=64)
172
+ amount = models.DecimalField("Цена в рублях", max_digits=12, decimal_places=2)
173
+ system = models.CharField(
174
+ "Платежная система",
175
+ max_length=20,
176
+ choices=System.choices,
177
+ default=System.CARD,
178
+ )
179
+ status = models.CharField("Статус платежа", max_length=40, default="Ожидает")
180
+ paid_on = models.DateField("Дата оплаты", null=True, blank=True)
181
+ external_id = models.CharField("Внешний идентификатор", max_length=80, blank=True)
182
+ comment = models.CharField("Комментарий кассира", max_length=200, blank=True)
183
+ currency = models.CharField("Валюта расчёта", max_length=12, default="RUB")
184
+ reviewed = models.BooleanField("Проверен", default=False)
185
+
186
+ class Meta:
187
+ verbose_name = "Платёж"
188
+ verbose_name_plural = "Платежи"
189
+ ordering = ["-id"]
190
+
191
+ def __str__(self) -> str:
192
+ return self.payer_name
193
+
194
+
163
195
  class Appointment(models.Model):
164
196
  """Kept on Django's calendar and clock widgets (no native date mixin)."""
165
197
 
@@ -1,3 +1,3 @@
1
1
  """Phone ergonomics for the native Django admin."""
2
2
 
3
- __version__ = "0.2.4"
3
+ __version__ = "0.2.6"
@@ -90,8 +90,11 @@ html.admin-mobile .admin-mobile-native {
90
90
  background: var(--body-bg);
91
91
  }
92
92
 
93
- html.admin-mobile-cards #result_list tbody tr.selected {
94
- background: var(--selected-bg);
93
+ html.admin-mobile-cards #result_list tbody tr.selected,
94
+ html.admin-mobile-cards #changelist tbody tr:has(.action-select:checked) {
95
+ background: color-mix(in srgb, var(--button-bg) 14%, var(--body-bg));
96
+ border-color: color-mix(in srgb, var(--button-bg) 55%, var(--hairline-color));
97
+ box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--button-bg) 65%, transparent);
95
98
  }
96
99
 
97
100
  html.admin-mobile-cards #result_list tbody td,
@@ -674,12 +677,17 @@ html.admin-mobile-cards .admin-mobile-select-all {
674
677
  height: 22px;
675
678
  }
676
679
 
677
- html.admin-mobile-cards #result_list tbody input:not([type="checkbox"]):not([type="hidden"]),
678
- html.admin-mobile-cards #result_list tbody select {
679
- width: auto;
680
- max-width: 58%;
680
+ html.admin-mobile-cards #result_list tbody .admin-mobile-value input:not([type="checkbox"]):not([type="hidden"]),
681
+ html.admin-mobile-cards #result_list tbody .admin-mobile-value select,
682
+ html.admin-mobile-cards #result_list tbody .admin-mobile-value textarea {
683
+ display: block;
684
+ width: 100%;
685
+ max-width: 100%;
686
+ min-width: 0;
681
687
  min-height: 44px;
688
+ margin: 0;
682
689
  font-size: 16px;
690
+ text-align: end;
683
691
  box-sizing: border-box;
684
692
  }
685
693