accrete 0.0.103__py3-none-any.whl → 0.0.105__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.
Files changed (251) hide show
  1. accrete/contrib/ui/__init__.py +6 -29
  2. accrete/contrib/ui/context.py +26 -294
  3. accrete/contrib/ui/filter.py +316 -324
  4. accrete/contrib/ui/middleware.py +44 -0
  5. accrete/contrib/ui/models.py +3 -0
  6. accrete/contrib/ui/static/bulma/README.md +4 -2
  7. accrete/contrib/ui/static/bulma/bulma.css +21551 -0
  8. accrete/contrib/ui/static/bulma/bulma.css.map +1 -0
  9. accrete/contrib/ui/static/bulma/bulma.scss +1 -1
  10. accrete/contrib/ui/static/bulma/css/bulma.css +1988 -2874
  11. accrete/contrib/ui/static/bulma/css/bulma.css.map +1 -1
  12. accrete/contrib/ui/static/bulma/css/bulma.min.css +2 -2
  13. accrete/contrib/ui/static/bulma/css/versions/bulma-no-dark-mode.css +19648 -0
  14. accrete/contrib/ui/static/bulma/css/versions/bulma-no-dark-mode.css.map +1 -0
  15. accrete/contrib/ui/static/bulma/css/versions/bulma-no-dark-mode.min.css +2 -2
  16. accrete/contrib/ui/static/bulma/css/versions/bulma-no-helpers-prefixed.css +11136 -0
  17. accrete/contrib/ui/static/bulma/css/versions/bulma-no-helpers-prefixed.css.map +1 -0
  18. accrete/contrib/ui/static/bulma/css/versions/bulma-no-helpers-prefixed.min.css +2 -2
  19. accrete/contrib/ui/static/bulma/css/versions/bulma-no-helpers.css +11136 -0
  20. accrete/contrib/ui/static/bulma/css/versions/bulma-no-helpers.css.map +1 -0
  21. accrete/contrib/ui/static/bulma/css/versions/bulma-no-helpers.min.css +2 -2
  22. accrete/contrib/ui/static/bulma/css/versions/bulma-prefixed.min.css +21550 -2
  23. accrete/contrib/ui/static/bulma/css/versions/bulma-prefixed.min.css.map +1 -1
  24. accrete/contrib/ui/static/bulma/css/versions/bulma-prefixed.min.min.css +3 -0
  25. accrete/contrib/ui/static/bulma/package.json +12 -11
  26. accrete/contrib/ui/static/bulma/sass/base/animations.css +15 -0
  27. accrete/contrib/ui/static/bulma/sass/base/animations.css.map +1 -0
  28. accrete/contrib/ui/static/bulma/sass/base/generic.css +196 -0
  29. accrete/contrib/ui/static/bulma/sass/base/generic.css.map +1 -0
  30. accrete/contrib/ui/static/bulma/sass/base/minireset.css +82 -0
  31. accrete/contrib/ui/static/bulma/sass/base/minireset.css.map +1 -0
  32. accrete/contrib/ui/static/bulma/sass/base/skeleton.css +113 -0
  33. accrete/contrib/ui/static/bulma/sass/base/skeleton.css.map +1 -0
  34. accrete/contrib/ui/static/bulma/sass/base/skeleton.scss +0 -12
  35. accrete/contrib/ui/static/bulma/sass/components/breadcrumb.css +108 -0
  36. accrete/contrib/ui/static/bulma/sass/components/breadcrumb.css.map +1 -0
  37. accrete/contrib/ui/static/bulma/sass/components/card.css +130 -0
  38. accrete/contrib/ui/static/bulma/sass/components/card.css.map +1 -0
  39. accrete/contrib/ui/static/bulma/sass/components/dropdown.css +119 -0
  40. accrete/contrib/ui/static/bulma/sass/components/dropdown.css.map +1 -0
  41. accrete/contrib/ui/static/bulma/sass/components/menu.css +119 -0
  42. accrete/contrib/ui/static/bulma/sass/components/menu.css.map +1 -0
  43. accrete/contrib/ui/static/bulma/sass/components/message.css +191 -0
  44. accrete/contrib/ui/static/bulma/sass/components/message.css.map +1 -0
  45. accrete/contrib/ui/static/bulma/sass/components/modal.css +194 -0
  46. accrete/contrib/ui/static/bulma/sass/components/modal.css.map +1 -0
  47. accrete/contrib/ui/static/bulma/sass/components/navbar.css +768 -0
  48. accrete/contrib/ui/static/bulma/sass/components/navbar.css.map +1 -0
  49. accrete/contrib/ui/static/bulma/sass/components/navbar.scss +41 -30
  50. accrete/contrib/ui/static/bulma/sass/components/pagination.css +302 -0
  51. accrete/contrib/ui/static/bulma/sass/components/pagination.css.map +1 -0
  52. accrete/contrib/ui/static/bulma/sass/components/panel.css +224 -0
  53. accrete/contrib/ui/static/bulma/sass/components/panel.css.map +1 -0
  54. accrete/contrib/ui/static/bulma/sass/components/panel.scss +2 -2
  55. accrete/contrib/ui/static/bulma/sass/components/tabs.css +192 -0
  56. accrete/contrib/ui/static/bulma/sass/components/tabs.css.map +1 -0
  57. accrete/contrib/ui/static/bulma/sass/elements/block.css +17 -0
  58. accrete/contrib/ui/static/bulma/sass/elements/block.css.map +1 -0
  59. accrete/contrib/ui/static/bulma/sass/elements/box.css +43 -0
  60. accrete/contrib/ui/static/bulma/sass/elements/box.css.map +1 -0
  61. accrete/contrib/ui/static/bulma/sass/elements/button.css +685 -0
  62. accrete/contrib/ui/static/bulma/sass/elements/button.css.map +1 -0
  63. accrete/contrib/ui/static/bulma/sass/elements/button.scss +9 -2
  64. accrete/contrib/ui/static/bulma/sass/elements/content.css +208 -0
  65. accrete/contrib/ui/static/bulma/sass/elements/content.css.map +1 -0
  66. accrete/contrib/ui/static/bulma/sass/elements/content.scss +8 -2
  67. accrete/contrib/ui/static/bulma/sass/elements/delete.css +60 -0
  68. accrete/contrib/ui/static/bulma/sass/elements/delete.css.map +1 -0
  69. accrete/contrib/ui/static/bulma/sass/elements/icon.css +51 -0
  70. accrete/contrib/ui/static/bulma/sass/elements/icon.css.map +1 -0
  71. accrete/contrib/ui/static/bulma/sass/elements/image.css +253 -0
  72. accrete/contrib/ui/static/bulma/sass/elements/image.css.map +1 -0
  73. accrete/contrib/ui/static/bulma/sass/elements/loader.css +14 -0
  74. accrete/contrib/ui/static/bulma/sass/elements/loader.css.map +1 -0
  75. accrete/contrib/ui/static/bulma/sass/elements/notification.css +213 -0
  76. accrete/contrib/ui/static/bulma/sass/elements/notification.css.map +1 -0
  77. accrete/contrib/ui/static/bulma/sass/elements/progress.css +119 -0
  78. accrete/contrib/ui/static/bulma/sass/elements/progress.css.map +1 -0
  79. accrete/contrib/ui/static/bulma/sass/elements/table.css +294 -0
  80. accrete/contrib/ui/static/bulma/sass/elements/table.css.map +1 -0
  81. accrete/contrib/ui/static/bulma/sass/elements/tag.css +252 -0
  82. accrete/contrib/ui/static/bulma/sass/elements/tag.css.map +1 -0
  83. accrete/contrib/ui/static/bulma/sass/elements/title.css +131 -0
  84. accrete/contrib/ui/static/bulma/sass/elements/title.css.map +1 -0
  85. accrete/contrib/ui/static/bulma/sass/form/checkbox-radio.css +72 -0
  86. accrete/contrib/ui/static/bulma/sass/form/checkbox-radio.css.map +1 -0
  87. accrete/contrib/ui/static/bulma/sass/form/checkbox-radio.scss +7 -3
  88. accrete/contrib/ui/static/bulma/sass/form/file.css +374 -0
  89. accrete/contrib/ui/static/bulma/sass/form/file.css.map +1 -0
  90. accrete/contrib/ui/static/bulma/sass/form/input-textarea.css +284 -0
  91. accrete/contrib/ui/static/bulma/sass/form/input-textarea.css.map +1 -0
  92. accrete/contrib/ui/static/bulma/sass/form/input-textarea.scss +0 -10
  93. accrete/contrib/ui/static/bulma/sass/form/select.css +347 -0
  94. accrete/contrib/ui/static/bulma/sass/form/select.css.map +1 -0
  95. accrete/contrib/ui/static/bulma/sass/form/select.scss +1 -0
  96. accrete/contrib/ui/static/bulma/sass/form/shared.css +48 -0
  97. accrete/contrib/ui/static/bulma/sass/form/shared.css.map +1 -0
  98. accrete/contrib/ui/static/bulma/sass/form/shared.scss +5 -1
  99. accrete/contrib/ui/static/bulma/sass/form/tools.css +356 -0
  100. accrete/contrib/ui/static/bulma/sass/form/tools.css.map +1 -0
  101. accrete/contrib/ui/static/bulma/sass/form/tools.scss +23 -12
  102. accrete/contrib/ui/static/bulma/sass/grid/columns-v2.css +1635 -0
  103. accrete/contrib/ui/static/bulma/sass/grid/columns-v2.css.map +1 -0
  104. accrete/contrib/ui/static/bulma/sass/grid/columns.css +1652 -0
  105. accrete/contrib/ui/static/bulma/sass/grid/columns.css.map +1 -0
  106. accrete/contrib/ui/static/bulma/sass/grid/columns.scss +109 -25
  107. accrete/contrib/ui/static/bulma/sass/grid/grid.css +3011 -0
  108. accrete/contrib/ui/static/bulma/sass/grid/grid.css.map +1 -0
  109. accrete/contrib/ui/static/bulma/sass/grid/grid.scss +3 -3
  110. accrete/contrib/ui/static/bulma/sass/helpers/aspect-ratio.css +61 -0
  111. accrete/contrib/ui/static/bulma/sass/helpers/aspect-ratio.css.map +1 -0
  112. accrete/contrib/ui/static/bulma/sass/helpers/border.css +17 -0
  113. accrete/contrib/ui/static/bulma/sass/helpers/border.css.map +1 -0
  114. accrete/contrib/ui/static/bulma/sass/helpers/color.css +5582 -0
  115. accrete/contrib/ui/static/bulma/sass/helpers/color.css.map +1 -0
  116. accrete/contrib/ui/static/bulma/sass/helpers/color.scss +166 -186
  117. accrete/contrib/ui/static/bulma/sass/helpers/flexbox.css +217 -0
  118. accrete/contrib/ui/static/bulma/sass/helpers/flexbox.css.map +1 -0
  119. accrete/contrib/ui/static/bulma/sass/helpers/float.css +37 -0
  120. accrete/contrib/ui/static/bulma/sass/helpers/float.css.map +1 -0
  121. accrete/contrib/ui/static/bulma/sass/helpers/gap.css +209 -0
  122. accrete/contrib/ui/static/bulma/sass/helpers/gap.css.map +1 -0
  123. accrete/contrib/ui/static/bulma/sass/helpers/other.css +34 -0
  124. accrete/contrib/ui/static/bulma/sass/helpers/other.css.map +1 -0
  125. accrete/contrib/ui/static/bulma/sass/helpers/overflow.css +65 -0
  126. accrete/contrib/ui/static/bulma/sass/helpers/overflow.css.map +1 -0
  127. accrete/contrib/ui/static/bulma/sass/helpers/position.css +45 -0
  128. accrete/contrib/ui/static/bulma/sass/helpers/position.css.map +1 -0
  129. accrete/contrib/ui/static/bulma/sass/helpers/spacing.css +489 -0
  130. accrete/contrib/ui/static/bulma/sass/helpers/spacing.css.map +1 -0
  131. accrete/contrib/ui/static/bulma/sass/helpers/typography.css +423 -0
  132. accrete/contrib/ui/static/bulma/sass/helpers/typography.css.map +1 -0
  133. accrete/contrib/ui/static/bulma/sass/helpers/visibility.css +485 -0
  134. accrete/contrib/ui/static/bulma/sass/helpers/visibility.css.map +1 -0
  135. accrete/contrib/ui/static/bulma/sass/layout/container.scss +16 -8
  136. accrete/contrib/ui/static/bulma/sass/layout/footer.css +9 -0
  137. accrete/contrib/ui/static/bulma/sass/layout/footer.css.map +1 -0
  138. accrete/contrib/ui/static/bulma/sass/layout/hero.css +534 -0
  139. accrete/contrib/ui/static/bulma/sass/layout/hero.css.map +1 -0
  140. accrete/contrib/ui/static/bulma/sass/layout/level.css +102 -0
  141. accrete/contrib/ui/static/bulma/sass/layout/level.css.map +1 -0
  142. accrete/contrib/ui/static/bulma/sass/layout/media.css +90 -0
  143. accrete/contrib/ui/static/bulma/sass/layout/media.css.map +1 -0
  144. accrete/contrib/ui/static/bulma/sass/layout/section.css +23 -0
  145. accrete/contrib/ui/static/bulma/sass/layout/section.css.map +1 -0
  146. accrete/contrib/ui/static/bulma/sass/layout/section.scss +4 -0
  147. accrete/contrib/ui/static/bulma/sass/themes/dark.css +3 -0
  148. accrete/contrib/ui/static/bulma/sass/themes/dark.css.map +1 -0
  149. accrete/contrib/ui/static/bulma/sass/themes/light.css +3 -0
  150. accrete/contrib/ui/static/bulma/sass/themes/light.css.map +1 -0
  151. accrete/contrib/ui/static/bulma/sass/themes/light.scss +1 -0
  152. accrete/contrib/ui/static/bulma/sass/themes/setup.css +3 -0
  153. accrete/contrib/ui/static/bulma/sass/themes/setup.css.map +1 -0
  154. accrete/contrib/ui/static/bulma/sass/utilities/controls.css +13 -0
  155. accrete/contrib/ui/static/bulma/sass/utilities/controls.css.map +1 -0
  156. accrete/contrib/ui/static/bulma/sass/utilities/css-variables.css +3 -0
  157. accrete/contrib/ui/static/bulma/sass/utilities/css-variables.css.map +1 -0
  158. accrete/contrib/ui/static/bulma/sass/utilities/css-variables.scss +3 -2
  159. accrete/contrib/ui/static/bulma/sass/utilities/derived-variables.css +3 -0
  160. accrete/contrib/ui/static/bulma/sass/utilities/derived-variables.css.map +1 -0
  161. accrete/contrib/ui/static/bulma/sass/utilities/extends.css +13 -0
  162. accrete/contrib/ui/static/bulma/sass/utilities/extends.css.map +1 -0
  163. accrete/contrib/ui/static/bulma/sass/utilities/functions.scss +2 -2
  164. accrete/contrib/ui/static/bulma/sass/utilities/initial-variables.css +3 -0
  165. accrete/contrib/ui/static/bulma/sass/utilities/initial-variables.css.map +1 -0
  166. accrete/contrib/ui/static/bulma/sass/utilities/initial-variables.scss +4 -4
  167. accrete/contrib/ui/static/bulma/sass/utilities/mixins.css +3 -0
  168. accrete/contrib/ui/static/bulma/sass/utilities/mixins.css.map +1 -0
  169. accrete/contrib/ui/static/bulma/sass/utilities/mixins.scss +1 -1
  170. accrete/contrib/ui/static/bulma/versions/bulma-no-dark-mode.css +19648 -0
  171. accrete/contrib/ui/static/bulma/versions/bulma-no-dark-mode.css.map +1 -0
  172. accrete/contrib/ui/static/bulma/versions/bulma-no-dark-mode.scss +2 -1
  173. accrete/contrib/ui/static/bulma/versions/bulma-no-helpers-prefixed.css +11136 -0
  174. accrete/contrib/ui/static/bulma/versions/bulma-no-helpers-prefixed.css.map +1 -0
  175. accrete/contrib/ui/static/bulma/versions/bulma-no-helpers-prefixed.scss +1 -1
  176. accrete/contrib/ui/static/bulma/versions/bulma-no-helpers.css +11136 -0
  177. accrete/contrib/ui/static/bulma/versions/bulma-no-helpers.css.map +1 -0
  178. accrete/contrib/ui/static/bulma/versions/bulma-no-helpers.scss +1 -1
  179. accrete/contrib/ui/static/bulma/versions/bulma-prefixed.css +21551 -0
  180. accrete/contrib/ui/static/bulma/versions/bulma-prefixed.css.map +1 -0
  181. accrete/contrib/ui/static/bulma/versions/bulma-prefixed.scss +1 -1
  182. accrete/contrib/ui/static/css/accrete.css +20757 -19997
  183. accrete/contrib/ui/static/css/accrete.css.map +1 -1
  184. accrete/contrib/ui/static/css/accrete.scss +185 -462
  185. accrete/contrib/ui/static/js/filter.js +97 -679
  186. accrete/contrib/ui/static/js/htmx.min.js +1 -1
  187. accrete/contrib/ui/templates/django/forms/widgets/date.html +5 -9
  188. accrete/contrib/ui/templates/django/forms/widgets/select.html +7 -5
  189. accrete/contrib/ui/templates/ui/content_right.html +7 -0
  190. accrete/contrib/ui/templates/ui/filter/filter.html +27 -0
  191. accrete/contrib/ui/templates/ui/filter/query_input.html +31 -0
  192. accrete/contrib/ui/templates/ui/filter/query_operator.html +11 -0
  193. accrete/contrib/ui/templates/ui/filter/query_params.html +106 -0
  194. accrete/contrib/ui/templates/ui/filter/query_tags.html +26 -0
  195. accrete/contrib/ui/templates/ui/layout.html +162 -233
  196. accrete/contrib/ui/templates/ui/list.html +39 -28
  197. accrete/contrib/ui/templates/ui/list_update.html +3 -0
  198. accrete/contrib/ui/templates/ui/message.html +13 -0
  199. accrete/contrib/ui/templates/ui/{partials/modal.html → modal.html} +9 -5
  200. accrete/contrib/ui/templates/ui/oob.html +3 -0
  201. accrete/contrib/ui/templates/ui/table.html +67 -71
  202. accrete/contrib/ui/templates/ui/table_row_update.html +14 -0
  203. accrete/contrib/ui/templates/ui/widgets/model_search_select.html +2 -2
  204. accrete/contrib/ui/templates/ui/widgets/model_search_select_multi.html +25 -14
  205. accrete/contrib/ui/templates/ui/widgets/model_search_select_options.html +1 -1
  206. accrete/contrib/ui/templatetags/{accrete_ui.py → ui.py} +68 -56
  207. accrete/contrib/ui/urls.py +3 -1
  208. accrete/contrib/ui/views.py +33 -3
  209. accrete/contrib/ui/widgets/__init__.py +1 -0
  210. accrete/contrib/ui/{forms/widgets.py → widgets/search_select.py} +7 -2
  211. accrete/contrib/user/templates/user/login.html +71 -23
  212. accrete/forms.py +0 -2
  213. accrete/managers.py +4 -4
  214. accrete/middleware.py +43 -66
  215. accrete/models.py +7 -1
  216. accrete/storage.py +4 -1
  217. accrete/tenant.py +9 -4
  218. accrete/utils/__init__.py +2 -0
  219. accrete/utils/models.py +9 -1
  220. accrete/utils/views.py +36 -20
  221. accrete/views.py +9 -5
  222. {accrete-0.0.103.dist-info → accrete-0.0.105.dist-info}/METADATA +2 -2
  223. accrete-0.0.105.dist-info/RECORD +370 -0
  224. {accrete-0.0.103.dist-info → accrete-0.0.105.dist-info}/WHEEL +1 -1
  225. accrete/contrib/ui/components/__init__.py +0 -1
  226. accrete/contrib/ui/components/search_select.py +0 -18
  227. accrete/contrib/ui/elements.py +0 -95
  228. accrete/contrib/ui/forms/__init__.py +0 -0
  229. accrete/contrib/ui/static/bulma/css/versions/bulma-no-dark-mode.min.css.map +0 -1
  230. accrete/contrib/ui/static/bulma/css/versions/bulma-no-helpers-prefixed.min.css.map +0 -1
  231. accrete/contrib/ui/static/bulma/css/versions/bulma-no-helpers.min.css.map +0 -1
  232. accrete/contrib/ui/static/bulma/sass/grid/columns-v2.scss +0 -957
  233. accrete/contrib/ui/static/js/ui.js +0 -30
  234. accrete/contrib/ui/templates/ui/dashboard.html +0 -7
  235. accrete/contrib/ui/templates/ui/detail.html +0 -19
  236. accrete/contrib/ui/templates/ui/form.html +0 -21
  237. accrete/contrib/ui/templates/ui/partials/filter.html +0 -146
  238. accrete/contrib/ui/templates/ui/partials/form_errors.html +0 -34
  239. accrete/contrib/ui/templates/ui/partials/header.html +0 -123
  240. accrete/contrib/ui/templates/ui/partials/modal_form.html +0 -46
  241. accrete/contrib/ui/templates/ui/partials/onchange_form.html +0 -1
  242. accrete/contrib/ui/templates/ui/partials/pagination_detail.html +0 -23
  243. accrete/contrib/ui/templates/ui/partials/pagination_list.html +0 -28
  244. accrete/contrib/ui/templates/ui/partials/table_field.html +0 -16
  245. accrete/contrib/ui/templates/ui/partials/table_field_float.html +0 -1
  246. accrete/contrib/ui/templates/ui/partials/table_field_monetary.html +0 -4
  247. accrete/contrib/ui/templates/ui/partials/table_field_string.html +0 -1
  248. accrete/contrib/ui/templates/ui/widgets/model_search_select_multi_selected_options.html +0 -3
  249. accrete/contrib/ui/templates/ui/widgets/model_search_select_multi_tags.html +0 -6
  250. accrete-0.0.103.dist-info/RECORD +0 -241
  251. {accrete-0.0.103.dist-info → accrete-0.0.105.dist-info}/licenses/LICENSE +0 -0
@@ -1,81 +1,77 @@
1
1
  {% extends 'ui/layout.html' %}
2
- {% load static %}
3
2
  {% load i18n %}
4
- {% load accrete_ui %}
3
+ {% load ui %}
4
+ {% load partials %}
5
5
 
6
- {% block tenant_switch_url %}{% endblock %}
7
-
8
- {% block content %}
9
- <table id="content-table" class="table is-fullwidth is-hoverable has-box" hx-indicator=".htmx-indicator">
10
- <thead style="position: sticky; top: 0; z-index: 10">
11
- {% block table_header_row %}
12
- <tr>
13
- {% block table_header %}
14
- <th>{{ object_label }}</th>
15
- {% for field in fields %}
16
- <th data-name="{{ field.name }}" style="text-align: {% firstof field.header_alignment.value field.alignment.value %}">{{ field.label }}</th>
17
- {% endfor %}
18
- {% if unselect_button %}
19
- <th></th>
20
- {% endif %}
21
- {% endblock %}
22
- </tr>
23
- {% endblock %}
6
+ {% block content_left %}
7
+ <table id="content-table" class="table can-compact is-fullwidth is-hoverable is-narrow mb-1" hx-indicator=".htmx-indicator" x-data="">
8
+ <thead style="position: sticky; top: 0; z-index: 10; background-color: var(--bulma-scheme-main)">
9
+ <tr>
10
+ <th>{{ object_label }}</th>
11
+ {% for field in fields %}
12
+ <th style="text-align: {{ page.object_list|table_alignment:field }}">{{ page.object_list|verbose_field_name:field }}</th>
13
+ {% endfor %}
14
+ </tr>
24
15
  </thead>
25
- <tbody id="content-table-body" style="z-index: 9">
26
- {% for obj in list_page %}
27
- {% block table_data_row %}
28
- <tr>
29
- {% block table_data %}
30
- <td>
31
- <a class="is-underlined" href="{{ obj.get_absolute_url }}{{ object_param_str }}">{{ obj }}</a>
32
- </td>
16
+ <tbody id="content-table-body" style="z-index: 9" x-ref="tbody">
17
+ {% for object in page.object_list %}
18
+ {% partialdef tr inline=True %}
19
+ <tr id="tr-{{ object.pk }}"
20
+ {% if detail_enabled %}
21
+ style="cursor: pointer;"
22
+ hx-get="{{ object.get_absolute_url }}{% querystring %}" hx-target="#content-right-header" hx-select="#content-right-header" hx-select-oob="#content-right" hx-swap="outerHTML"
23
+ x-data="{selected: false}" @unselect-tr.window="selected = false"
24
+ x-on:click="$dispatch('unselect-tr'); showContentRight = true; selected = true; $nextTick(() => { $el.scrollIntoView( {block: 'nearest'} ) });" x-bind:class="selected ? 'is-success' : ''"
25
+ {% endif %}
26
+ >
27
+ {% partialdef td inline=True %}
28
+ <td>{{ object }}</td>
33
29
  {% for field in fields %}
34
- {% if field.template %}
35
- {% include field.template %}
36
- {% else %}
37
- {% with val=obj|field_attr:field is_relation=field.is_relation %}
38
- <td style="text-align: {{ field.alignment.value }}" {% if val|length > field.truncate_after %}title="{{ val }}"{% endif %}>
39
- <span>
40
- <span class="responsive-heading has-text-weight-light" style="margin-right: .2rem">{{ field.label }}:</span>
41
- {% if is_relation and val.get_absolute_url %}<a href="{{ obj|related_obj_url:field.name }}" class="is-underlined">{% endif %}
42
- {{ field.prefix }}
43
- {% block td_content %}
44
- {% if field.truncate_after > 0 %}
45
- {{ val|default_if_none:'---'|truncatechars:field.truncate_after }}
46
- {% else %}
47
- {{ val|default_if_none:'---' }}
48
- {% endif %}
49
- {% endblock %}
50
- {{ field.suffix }}
51
- {% if is_relation %}</a>{% endif %}
52
- </span>
53
- </td>
54
- {% endwith %}
55
- {% endif %}
30
+ <td style="text-align: {{ object|table_alignment:field }}">
31
+ <span class="">
32
+ <span class="responsive-heading has-text-weight-light" style="margin-right: .2rem">{{ object|verbose_field_name:field }}:</span>
33
+ {{ object|table_display:field|default_if_none:'' }}
34
+ </span>
35
+ </td>
56
36
  {% endfor %}
57
- {% if unselect_button %}
58
- <td><button class="button is-small has-icon p-0 is-pulled-right" onclick="unselectSingleObject({{ obj.pk }})"><i class="icon-delete-filter"></i></button></td>
59
- {% endif %}
60
- {% endblock %}
37
+ {% endpartialdef %}
61
38
  </tr>
62
- {% endblock %}
39
+ {% endpartialdef %}
63
40
  {% endfor %}
64
41
  </tbody>
42
+ <tfoot style="position: sticky; bottom: 0; z-index: 10; background-color: var(--bulma-scheme-main);" class="has-text-weight-bold">
43
+ <tr id="tf-row">
44
+ {% partialdef tf inline=True %}
45
+ <td></td>
46
+ {% for field in fields %}
47
+ {% if field in footer %}
48
+ <td style="text-align: {{ queryset|table_alignment:field }}">
49
+ <span class="">
50
+ <span class="responsive-heading has-text-weight-light" style="margin-right: .2rem">{{ queryset|verbose_field_name:field }}:</span>
51
+ {{ footer|get_item:field }}
52
+ </span>
53
+ </td>
54
+ {% else %}
55
+ <td></td>
56
+ {% endif %}
57
+ {% endfor %}
58
+ {% endpartialdef %}
59
+ </tr>
60
+ </tfoot>
65
61
  </table>
66
- {% if endless_scroll %}
67
- <div id="endless-scroller"
68
- {% if list_page.has_next %}
69
- hx-get="{{ pagination_param_str }}&page={{ list_page.next_page_number }}"
70
- hx-trigger="intersect once"
71
- hx-select="tbody > tr"
72
- hx-target="#content-table-body"
73
- hx-swap="beforeend"
74
- hx-select-oob="#list-pagination-end-index,#list-pagination-next-button,#list-pagination-prev-button,#endless-scroller"
75
- hx-indicator="#endless-scroll-indicator"
76
- {% endif %}
77
- >
78
- </div>
79
- <progress id="endless-scroll-indicator" class="htmx-indicator progress is-small is-success" max="100">15%</progress>
80
- {% endif %}
81
- {% endblock %}
62
+
63
+ <div id="endless-scroller"
64
+ {% if page.has_next %}
65
+ hx-get="{% querystring page=page.next_page_number %}"
66
+ hx-trigger="intersect once"
67
+ hx-select="tbody > tr"
68
+ hx-target="#content-table-body"
69
+ hx-swap="beforeend"
70
+ hx-select-oob="#pagination-next-button,#pagination-end-index,#endless-scroller"
71
+ hx-indicator="#endless-scroll-indicator"
72
+ hx-replace-url="true"
73
+ {% endif %}
74
+ >
75
+ </div>
76
+ <progress id="endless-scroll-indicator" class="htmx-indicator progress is-small is-success" max="100">15%</progress>
77
+ {% endblock %}
@@ -0,0 +1,14 @@
1
+ <table>
2
+ <tbody>
3
+ <tr hx-swap-oob="innerHTML:#tr-{{ object.pk }}">
4
+ {% include 'ui/table.html#td' with object=object fields=fields queryset=queryset %}
5
+ </tr>
6
+ </tbody>
7
+ {% if footer %}
8
+ <tfoot>
9
+ <tr hx-swap-oob="innerHTML:#tf-row">
10
+ {% include 'ui/table.html#tf' with object=object fields=fields queryset=queryset %}
11
+ </tr>
12
+ </tfoot>
13
+ {% endif %}
14
+ </table>
@@ -3,14 +3,14 @@
3
3
 
4
4
 
5
5
  <div class="field select" x-data="{open: false, shouldClose(event) {return event.relatedTarget == $refs.dropdownContent || $refs.dropdownContent.contains(event.relatedTarget);} }"
6
- @click.outside="open = false"
6
+ @click.outside="open = false" hx-disinherit="*"
7
7
  >
8
8
  <input id="id_{{ widget.name }}_value" hidden="hidden" type="{{ widget.type }}" name="{{ widget.name }}" x-ref="inputValue" aria-label="inputValue"
9
9
  value="{{ widget.value }}"
10
10
  >
11
11
  <input id="id_{{ widget.name }}_display" class="input" type="text" readonly x-ref="inputDisplay" value="{{ widget.value_display }}" aria-label="inputDisplay"
12
12
  style="padding-right: 30px"
13
- x-on:focus="open = true;"
13
+ x-on:focus="open = !open;"
14
14
  x-on:keydown="if ($event.keyCode == 27) {document.activeElement.blur()} else if ($event.keyCode != 9) {$refs.searchInput.focus();}"
15
15
  x-on:focusout="open = shouldClose($event)"
16
16
  >
@@ -1,10 +1,13 @@
1
1
  {% load i18n %}
2
+ {% load ui %}
2
3
 
3
4
  <div class="" x-data="{open: false, shouldClose(event) {return event.relatedTarget == $refs.dropdownContent || $refs.dropdownContent.contains(event.relatedTarget);} }"
4
- @click.outside="open = false" style="width: 100%"
5
+ @click.outside="open = false" style="width: 100%;" hx-disinherit="*"
5
6
  >
6
7
  <select multiple id="{{ widget.attrs.id }}" hidden="hidden" name="{{ widget.name }}" aria-label="{{ widget.name }}" x-ref="inputValue">
7
- {% include 'ui/widgets/model_search_select_multi_selected_options.html' %}
8
+ {% for obj in selected %}
9
+ <option selected value="{{ obj.pk }}"></option>
10
+ {% endfor %}
8
11
  </select>
9
12
  <div id="{{ widget.attrs.id }}_display" class="input select py-1 pl-1" tabindex="0" x-ref="inputDisplay" aria-label="inputDisplay"
10
13
  style="padding-right: 30px; border-radius: 0; border-top: 0; border-right:0; border-left: 0; min-height: var(--bulma-control-height); height: fit-content; width: 100%"
@@ -18,23 +21,32 @@
18
21
  let val = $event.target.getAttribute('data-value');
19
22
  $refs.inputValue.querySelector(`option[value=${CSS.escape(val)}]`).remove();
20
23
  $event.target.parentElement.remove();
24
+ $dispatch('change');
21
25
  }
22
- ">
23
- {% include 'ui/widgets/model_search_select_multi_tags.html' %}
26
+ "
27
+ >
28
+ {% for obj in selected %}
29
+ <span class="tag has-text-weight-normal is-medium">
30
+ {{ obj }}
31
+ <button class="delete" type="button" data-value="{{ obj.pk }}"></button>
32
+ </span>
33
+ {% endfor %}
24
34
  </div>
25
35
  </div>
26
- <div style="position: relative; z-index: 90;">
27
- <div x-show="open" class="box pt-1 mb-2" x-ref="dropdownContent" tabindex="-1" x-transition style="position: absolute; width: 100%;">
28
- <input id="{{ widget.attrs.id }}_search" type="search" autocomplete="off" class="input" x-ref="searchInput" aria-label="search"
36
+ <div style="position: relative; top: 10px; z-index: 9">
37
+ <div x-show="open" class="box pt-1 mb-2" x-ref="dropdownContent" x-cloak="" tabindex="-1" x-transition style="position: absolute; width: 100%;">
38
+ <input id="id_{{ widget.uuid }}_search" type="search" autocomplete="off" class="input" x-ref="searchInput" aria-label="search"
29
39
  name="{{ widget.search_parameter }}"
30
40
  placeholder="{% translate 'Type to search' %}"
31
41
  x-on:keydown="if ($event.keyCode == 27) {document.activeElement.blur()}"
32
42
  x-on:focusout="open = shouldClose($event)"
33
43
  hx-get="{{ widget.search_url }}"
34
- hx-trigger="input changed delay:500ms, search"
35
- hx-target="#{{ widget.attrs.id }}_dropdown_items"
44
+ hx-trigger="input changed delay:300ms, search"
45
+ hx-target="#id_{{ widget.uuid }}_dropdown_items"
46
+ hx-swap="innerHTML"
47
+ @change.stop=""
36
48
  >
37
- <div id="{{ widget.attrs.id }}_dropdown_items" class="hoverable" style="max-height: 200px; width: 100%; overflow-y: auto;"
49
+ <div id="id_{{ widget.uuid }}_dropdown_items" class="hoverable" style="max-height: 200px; width: 100%; overflow-y: auto;"
38
50
  x-on:click="
39
51
  if (! $refs.inputValue.querySelectorAll(`option[value=${CSS.escape($event.target.value)}]`).length) {
40
52
  let option = document.createElement('option');
@@ -42,16 +54,15 @@
42
54
  let delButton = document.createElement('button');
43
55
  option.setAttribute('selected', '');
44
56
  option.value = $event.target.value;
45
- tag.classList.add('tag');
57
+ tag.classList.add('tag', 'has-text-weight-normal', 'is-medium');
46
58
  tag.innerText = $event.target.innerText;
47
- tag.style.whiteSpace = 'normal';
48
- tag.style.height = 'fit-content';
49
- delButton.classList.add('delete', 'is-small');
59
+ delButton.classList.add('delete');
50
60
  delButton.type = 'button';
51
61
  delButton.setAttribute('data-value', $event.target.value);
52
62
  tag.appendChild(delButton);
53
63
  $refs.inputValue.appendChild(option);
54
64
  $refs.inputDisplayTags.appendChild(tag);
65
+ $dispatch('change');
55
66
  };
56
67
  {% if widget.hx_trigger_on_change %}htmx.trigger('#{{ widget.attrs.id }}_value', 'change');{% endif %}
57
68
  "
@@ -1,3 +1,3 @@
1
1
  {% for option in options %}
2
2
  <button type="button" class="dropdown-item px-1" value="{{ option.pk }}" style="word-wrap: break-word; width: 100%; white-space: normal">{{ option }}</button>
3
- {% endfor %}
3
+ {% endfor %}
@@ -1,15 +1,14 @@
1
1
  import logging
2
+ import re
2
3
  from datetime import datetime, date, timedelta
4
+
3
5
  from django.utils.translation import gettext_lazy as _
4
6
  from django import template
5
- from django.db.models import Manager
6
- from django.forms import Form, ModelForm
7
+ from django.db.models import Manager, DecimalField, IntegerField, FloatField, Model
7
8
  from django.conf import settings
8
9
  from django.template.loader import render_to_string
9
10
  from django.utils.safestring import mark_safe
10
11
 
11
- from accrete.contrib.ui import TableField, TableFieldType
12
-
13
12
  _logger = logging.getLogger(__name__)
14
13
  register = template.Library()
15
14
 
@@ -27,34 +26,19 @@ def combine_templates(template_name, request=None):
27
26
  return mark_safe(html)
28
27
 
29
28
 
30
- @register.filter(name='field_attr')
31
- def get_attr_from_field(obj: object, field: TableField):
32
-
33
- def return_save(attr):
34
- if isinstance(attr, Manager):
35
- return attr.related_model
36
- if attr is None:
37
- return None
38
- if isinstance(attr, str):
39
- return attr
40
- return attr
41
- f_name = field.name
42
- if field.field_type == TableFieldType.CHOICE_DISPLAY:
43
- f_name = f'get_{f_name}_display'
44
-
45
- try:
46
- attribute = getattr(obj, f_name, False)
47
- except (AttributeError,):
48
- _logger.warning(f'Object {obj} has no attribute {f_name}')
49
- attribute = None
50
- return return_save(attribute)
29
+ @register.filter(name='related_obj_url')
30
+ def related_obj_url(param: object, value: str):
31
+ attr = getattr(param, value, False)
32
+ if attr and hasattr(attr, 'get_absolute_url'):
33
+ return attr.get_absolute_url()
34
+ return '#'
51
35
 
52
36
 
53
37
  @register.filter(name='get_attr')
54
38
  def get_attr_from_string(param: object, value: str):
55
39
 
56
40
  def return_save(attr):
57
- if isinstance(attr, Manager):
41
+ if isinstance(attr, Manager) and hasattr(attr, 'related_model'):
58
42
  return attr.related_model
59
43
  if attr is None:
60
44
  return None
@@ -70,43 +54,67 @@ def get_attr_from_string(param: object, value: str):
70
54
  return return_save(attribute)
71
55
 
72
56
 
73
- @register.filter(name='related_obj_url')
74
- def related_obj_url(param: object, value: str):
75
- attr = getattr(param, value, False)
76
- if attr and hasattr(attr, 'get_absolute_url'):
77
- return attr.get_absolute_url()
78
- return '#'
57
+ @register.filter(name='has_attr')
58
+ def has_attr(param: object, value:str):
59
+ return hasattr(param, value)
79
60
 
80
61
 
81
- @register.filter(name='message_class')
82
- def message_class(param):
83
- if param.level == 25:
84
- return 'is-success'
85
- if param.level == 30:
86
- return 'is-warning'
87
- if param.level == 40:
88
- return 'is-danger'
62
+ @register.filter(name='get_item')
63
+ def get_item(param, value):
64
+ return param[value]
89
65
 
90
66
 
91
- @register.filter(name='non_field_error_code')
92
- def non_field_error_code(form: [Form|ModelForm], code: str) -> bool:
93
- if not form:
94
- return False
95
- for error in form.non_field_errors().as_data():
96
- if error.code and error.code == code:
97
- return True
98
- return False
67
+ @register.filter(name='get_model')
68
+ def get_model(instance):
69
+ return instance._meta.model
99
70
 
100
71
 
101
- @register.filter(name='extract_non_field_error')
102
- def extract_non_field_error(form: [Form|ModelForm], code: str) -> str:
103
- if not form:
72
+ @register.filter(name='verbose_field_name')
73
+ def verbose_field_name(param: object, value: str):
74
+ if not param:
104
75
  return ''
105
- errors = []
106
- for error in form.non_field_errors().as_data():
107
- if error.code and error.code == code:
108
- errors.append(str(error.message))
109
- return mark_safe('<br>'.join(errors))
76
+ if isinstance(param, Model):
77
+ name = param._meta.get_field(value).verbose_name
78
+ else:
79
+ name = getattr(param.model, value).field.verbose_name
80
+ return name
81
+
82
+
83
+ @register.filter(name='table_display')
84
+ def table_display(param: object, value: str):
85
+ field = getattr(param, value)
86
+ if isinstance(field, Manager):
87
+ return mark_safe(f"""
88
+ <span>
89
+ <div class="tags">
90
+ {''.join(['<span class="tag">{}</span>'.format(o) for o in field.all()])}
91
+ </div>
92
+ </span>
93
+ """)
94
+ return get_attr_from_string(param, value)
95
+
96
+
97
+ @register.filter(name='table_alignment')
98
+ def table_alignment(param, value):
99
+ if isinstance(param, str):
100
+ return 'left'
101
+ if isinstance(param, Model):
102
+ field = param._meta.get_field(value)
103
+ else:
104
+ field = getattr(param.model, value).field
105
+ if isinstance(field, (DecimalField, IntegerField, FloatField)):
106
+ return 'right'
107
+ return 'left'
108
+
109
+
110
+ @register.filter(name='message_class')
111
+ def message_class(message):
112
+ if message.level == 25:
113
+ return 'is-success'
114
+ if message.level == 30:
115
+ return 'is-warning'
116
+ if message.level == 40:
117
+ return 'is-danger'
110
118
 
111
119
 
112
120
  @register.filter(name='timedelta_cast')
@@ -133,3 +141,7 @@ def datetime_to_weekday(dt: datetime|date, default=None) -> str:
133
141
  7: _('Sun')
134
142
  }
135
143
  return mapping[dt.isoweekday()]
144
+
145
+ @register.filter(name='xrefsave')
146
+ def x_ref_save(param: str):
147
+ return re.sub(r'[^A-Za-z]+','', param)
@@ -5,5 +5,7 @@ from . import views
5
5
  app_name = 'ui'
6
6
 
7
7
  urlpatterns = [
8
- path('', views.home, name='home')
8
+ path('filter/<str:model>/params/', views.params, name='filter_params'),
9
+ path('filter/<str:model>/input/', views.set_filter_input, name='filter_input'),
10
+ path('filter/<str:model>/query/add/', views.filter_add_query, name='filter_add_query')
9
11
  ]
@@ -1,5 +1,35 @@
1
- from django.shortcuts import render
1
+ import json
2
2
 
3
+ from django.contrib.auth.decorators import login_required
4
+ from django.apps import apps
5
+ from django.http import HttpResponse
6
+ from .filter import Filter
3
7
 
4
- def home(request):
5
- return render(request, 'ui/layout.html', {})
8
+
9
+ @login_required
10
+ def params(request, model: str):
11
+ app_label, model_name = model.split('.')
12
+ Model = apps.get_model(app_label, model_name)
13
+ return HttpResponse(Filter(Model, request.GET).query_params())
14
+
15
+
16
+ @login_required
17
+ def set_filter_input(request, model: str):
18
+ app_label, model_name = model.split('.')
19
+ Model = apps.get_model(app_label, model_name)
20
+ lookup = request.GET.get('lookup')
21
+ return HttpResponse(Filter(Model, request.GET).query_input(lookup))
22
+
23
+
24
+ @login_required
25
+ def filter_add_query(request, model: str):
26
+ app_label, model_name = model.split('.')
27
+ Model = apps.get_model(app_label, model_name)
28
+ query = json.loads(request.GET.get('q', '[]'))
29
+ lookup = request.GET.get('filter_lookup')
30
+ value = request.GET.get('filter_input')
31
+ query.append({lookup: value})
32
+ query = json.dumps(query)
33
+ query_dict = request.GET.copy()
34
+ query_dict.update(q=query)
35
+ return HttpResponse(Filter(Model, query_dict).query_tags())
@@ -0,0 +1 @@
1
+ from .search_select import ModelSearchSelect, ModelSearchSelectMulti
@@ -1,3 +1,4 @@
1
+ from uuid import uuid4
1
2
  from django.forms import widgets
2
3
  from django.shortcuts import resolve_url
3
4
 
@@ -26,6 +27,7 @@ class ModelSearchSelect(widgets.NumberInput):
26
27
  qs = self.choices.queryset
27
28
  if self.limit:
28
29
  qs = qs[:self.limit]
30
+ uuid = str(uuid4())
29
31
 
30
32
  context = {
31
33
  "widget": {
@@ -38,7 +40,8 @@ class ModelSearchSelect(widgets.NumberInput):
38
40
  "template_name": self.template_name,
39
41
  'search_url': self.search_url,
40
42
  'search_parameter': self.search_parameter,
41
- 'hx_trigger_on_change': self.hx_trigger_on_change
43
+ 'hx_trigger_on_change': self.hx_trigger_on_change,
44
+ 'uuid': uuid
42
45
  },
43
46
  'options': qs
44
47
  }
@@ -82,6 +85,7 @@ class ModelSearchSelectMulti(widgets.SelectMultiple):
82
85
  qs = self.choices.queryset
83
86
  if self.limit:
84
87
  qs = qs[:self.limit]
88
+ uuid = uuid4()
85
89
 
86
90
  context = {
87
91
  "widget": {
@@ -93,7 +97,8 @@ class ModelSearchSelectMulti(widgets.SelectMultiple):
93
97
  "template_name": self.template_name,
94
98
  'search_url': resolve_url(self.search_url),
95
99
  'search_parameter': self.search_parameter,
96
- 'hx_trigger_on_change': self.hx_trigger_on_change
100
+ 'hx_trigger_on_change': self.hx_trigger_on_change,
101
+ 'uuid': uuid
97
102
  },
98
103
  'options': qs,
99
104
  'selected': self.choices.queryset.filter(pk__in=value) if value else qs.none()
@@ -2,33 +2,81 @@
2
2
  {% load static %}
3
3
  {% load i18n %}
4
4
 
5
- {% block title %}Login | Accrete{% endblock %}
5
+ {% block title %}Login{% endblock %}
6
6
 
7
7
  {% block body %}
8
- <section class="hero is-primary is-medium is-bold is-fullheight">
9
- <div class="hero-body">
10
- <div class="container">
11
- <div class="columns">
12
- <div class="column box is-8-tablet is-offset-2-tablet is-6-desktop is-offset-3-desktop is-4-fullhd is-offset-4-fullhd p-3">
13
- <form method="POST" action="" hx-boost="false">
14
- {% csrf_token %}
15
- <span class="has-text-danger is-size-7">{{ form.non_field_errors }}</span>
16
-
17
- <label class="label">{{ form.username.label_tag }}
18
- {{ form.username }}
19
- <span class="has-text-danger is-size-7">{{ form.username.errors }}</span>
20
- </label>
21
-
22
- <label class="label">{{ form.password.label_tag }}
23
- {{form.password}}
24
- <span class="has-text-danger is-size-7">{{ form.password.errors }}</span>
25
- </label>
8
+ <section class="hero is-success is-fullheight">
9
+ <!-- Hero head: will stick at the top -->
10
+ <div class="hero-head">
11
+ <header class="navbar">
12
+ <div class="container">
13
+ <div class="navbar-brand">
14
+ <p class="title navbar-item">HRP</p>
15
+ <span class="navbar-burger" data-target="navbarMenuHeroC">
16
+ <span></span>
17
+ <span></span>
18
+ <span></span>
19
+ <span></span>
20
+ </span>
21
+ </div>
22
+ {# <div id="navbarMenuHeroC" class="navbar-menu">#}
23
+ {# <div class="navbar-end">#}
24
+ {# <a class="navbar-item is-active"> Home </a>#}
25
+ {# <a class="navbar-item"> Examples </a>#}
26
+ {# <a class="navbar-item"> Documentation </a>#}
27
+ {# <span class="navbar-item">#}
28
+ {# <a class="button is-success is-inverted">#}
29
+ {# <span class="icon">#}
30
+ {# <i class="fab fa-github"></i>#}
31
+ {# </span>#}
32
+ {# <span>Download</span>#}
33
+ {# </a>#}
34
+ {# </span>#}
35
+ {# </div>#}
36
+ {# </div>#}
37
+ </div>
38
+ </header>
39
+ </div>
26
40
 
27
- <input type="submit" class="button is-fullwidth is-success is-medium" value="{% translate 'Login' %}">
28
- </form>
41
+ <!-- Hero content: will be in the middle -->
42
+ <div class="hero-body">
43
+ <div class="container">
44
+ <div class="columns">
45
+ <div class="column box is-8-tablet is-offset-2-tablet is-6-desktop is-offset-3-desktop is-4-fullhd is-offset-4-fullhd p-3">
46
+ <form method="POST" action="" hx-boost="false">
47
+ {% csrf_token %}
48
+ <span class="has-text-danger is-size-7">{{ form.non_field_errors }}</span>
49
+ <label class="label">
50
+ {{ form.username.label_tag }}
51
+ {{ form.username }}
52
+ <span class="has-text-danger is-size-7">{{ form.username.errors }}</span>
53
+ </label>
54
+ <label class="label">{{ form.password.label_tag }}
55
+ {{ form.password }}
56
+ <span class="has-text-danger is-size-7">{{ form.password.errors }}</span>
57
+ </label>
58
+ <input type="submit" class="button is-fullwidth is-success is-medium"
59
+ value="{% translate 'Login' %}">
60
+ </form>
61
+ </div>
29
62
  </div>
30
63
  </div>
31
64
  </div>
32
- </div>
33
- </section>
65
+
66
+ <!-- Hero footer: will stick at the bottom -->
67
+ <div class="hero-foot">
68
+ <nav class="tabs is-boxed is-fullwidth">
69
+ <div class="container">
70
+ <ul>
71
+ {# <li class="is-active"><a>Overview</a></li>#}
72
+ {# <li><a>Modifiers</a></li>#}
73
+ {# <li><a>Grid</a></li>#}
74
+ {# <li><a>Elements</a></li>#}
75
+ {# <li><a>Components</a></li>#}
76
+ {# <li><a>Layout</a></li>#}
77
+ </ul>
78
+ </div>
79
+ </nav>
80
+ </div>
81
+ </section>
34
82
  {% endblock %}
accrete/forms.py CHANGED
@@ -1,10 +1,8 @@
1
1
  import logging
2
2
  from django import forms
3
- from django.contrib.auth import get_user_model
4
3
  from accrete.tenant import get_tenant
5
4
 
6
5
  _logger = logging.getLogger(__name__)
7
- User = get_user_model()
8
6
 
9
7
 
10
8
  class TenantForm(forms.Form):