WuttaWeb 0.19.0__tar.gz → 0.19.2__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 (202) hide show
  1. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/CHANGELOG.md +30 -0
  2. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/PKG-INFO +2 -2
  3. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/pyproject.toml +2 -2
  4. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/forms/schema.py +69 -19
  5. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/forms/widgets.py +44 -7
  6. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/grids/base.py +125 -28
  7. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/progress.py +4 -1
  8. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/base.mako +2 -2
  9. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/batch/view.mako +1 -14
  10. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/master/view.mako +15 -0
  11. wuttaweb-0.19.0/tests/util.py → wuttaweb-0.19.2/src/wuttaweb/testing.py +26 -39
  12. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/util.py +33 -6
  13. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/views/batch.py +11 -1
  14. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/views/master.py +87 -1
  15. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/db/test_continuum.py +1 -2
  16. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/forms/test_schema.py +152 -94
  17. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/forms/test_widgets.py +132 -93
  18. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/grids/test_base.py +96 -1
  19. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/grids/test_filters.py +1 -1
  20. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/test_auth.py +1 -1
  21. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/test_handler.py +1 -1
  22. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/test_menus.py +1 -1
  23. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/test_progress.py +5 -2
  24. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/test_util.py +17 -6
  25. wuttaweb-0.19.2/tests/util.py +40 -0
  26. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/views/test___init__.py +1 -1
  27. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/views/test_auth.py +1 -1
  28. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/views/test_base.py +1 -1
  29. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/views/test_batch.py +7 -1
  30. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/views/test_common.py +1 -1
  31. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/views/test_email.py +1 -1
  32. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/views/test_essential.py +1 -1
  33. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/views/test_master.py +51 -1
  34. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/views/test_people.py +1 -1
  35. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/views/test_progress.py +1 -1
  36. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/views/test_roles.py +1 -1
  37. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/views/test_settings.py +1 -1
  38. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/views/test_upgrades.py +1 -1
  39. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/views/test_users.py +1 -1
  40. wuttaweb-0.19.0/tests/views/__init__.py +0 -0
  41. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/.gitignore +0 -0
  42. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/COPYING.txt +0 -0
  43. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/README.md +0 -0
  44. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/Makefile +0 -0
  45. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/_static/.keepme +0 -0
  46. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.app.rst +0 -0
  47. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.auth.rst +0 -0
  48. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.cli.rst +0 -0
  49. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.cli.webapp.rst +0 -0
  50. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.conf.rst +0 -0
  51. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.db.continuum.rst +0 -0
  52. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.db.rst +0 -0
  53. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.db.sess.rst +0 -0
  54. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.emails.rst +0 -0
  55. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.forms.base.rst +0 -0
  56. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.forms.rst +0 -0
  57. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.forms.schema.rst +0 -0
  58. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.forms.widgets.rst +0 -0
  59. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.grids.base.rst +0 -0
  60. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.grids.filters.rst +0 -0
  61. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.grids.rst +0 -0
  62. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.handler.rst +0 -0
  63. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.helpers.rst +0 -0
  64. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.menus.rst +0 -0
  65. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.progress.rst +0 -0
  66. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.rst +0 -0
  67. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.static.rst +0 -0
  68. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.subscribers.rst +0 -0
  69. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.util.rst +0 -0
  70. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.views.auth.rst +0 -0
  71. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.views.base.rst +0 -0
  72. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.views.batch.rst +0 -0
  73. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.views.common.rst +0 -0
  74. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.views.email.rst +0 -0
  75. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.views.essential.rst +0 -0
  76. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.views.master.rst +0 -0
  77. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.views.people.rst +0 -0
  78. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.views.progress.rst +0 -0
  79. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.views.roles.rst +0 -0
  80. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.views.rst +0 -0
  81. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.views.settings.rst +0 -0
  82. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.views.upgrades.rst +0 -0
  83. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/api/wuttaweb.views.users.rst +0 -0
  84. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/conf.py +0 -0
  85. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/glossary.rst +0 -0
  86. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/index.rst +0 -0
  87. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/make.bat +0 -0
  88. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/narr/cli/builtin.rst +0 -0
  89. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/narr/cli/index.rst +0 -0
  90. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/narr/templates/base.rst +0 -0
  91. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/narr/templates/index.rst +0 -0
  92. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/narr/templates/lookup.rst +0 -0
  93. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/docs/narr/templates/overview.rst +0 -0
  94. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/__init__.py +0 -0
  95. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/_version.py +0 -0
  96. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/app.py +0 -0
  97. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/auth.py +0 -0
  98. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/cli/__init__.py +0 -0
  99. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/cli/webapp.py +0 -0
  100. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/conf.py +0 -0
  101. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/db/__init__.py +0 -0
  102. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/db/continuum.py +0 -0
  103. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/db/sess.py +0 -0
  104. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/email-templates/feedback.html.mako +0 -0
  105. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/email-templates/feedback.txt.mako +0 -0
  106. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/emails.py +0 -0
  107. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/forms/__init__.py +0 -0
  108. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/forms/base.py +0 -0
  109. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/grids/__init__.py +0 -0
  110. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/grids/filters.py +0 -0
  111. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/handler.py +0 -0
  112. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/helpers.py +0 -0
  113. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/menus.py +0 -0
  114. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/static/__init__.py +0 -0
  115. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/static/img/favicon.ico +0 -0
  116. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/static/img/logo.png +0 -0
  117. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/static/img/testing.png +0 -0
  118. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/subscribers.py +0 -0
  119. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/appinfo/configure.mako +0 -0
  120. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/appinfo/index.mako +0 -0
  121. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/auth/change_password.mako +0 -0
  122. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/auth/login.mako +0 -0
  123. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/base_meta.mako +0 -0
  124. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/configure.mako +0 -0
  125. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/deform/checkbox.pt +0 -0
  126. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/deform/checkbox_choice.pt +0 -0
  127. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/deform/checked_password.pt +0 -0
  128. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/deform/dateinput.pt +0 -0
  129. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/deform/datetimeinput.pt +0 -0
  130. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/deform/moneyinput.pt +0 -0
  131. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/deform/password.pt +0 -0
  132. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/deform/permissions.pt +0 -0
  133. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/deform/readonly/checkbox.pt +0 -0
  134. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/deform/readonly/email_recips.pt +0 -0
  135. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/deform/readonly/filedownload.pt +0 -0
  136. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/deform/readonly/notes.pt +0 -0
  137. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/deform/readonly/objectref.pt +0 -0
  138. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/deform/readonly/permissions.pt +0 -0
  139. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/deform/readonly/rolerefs.pt +0 -0
  140. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/deform/select.pt +0 -0
  141. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/deform/textarea.pt +0 -0
  142. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/deform/textinput.pt +0 -0
  143. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/email/settings/view.mako +0 -0
  144. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/forbidden.mako +0 -0
  145. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/form.mako +0 -0
  146. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/forms/vue_template.mako +0 -0
  147. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/grids/table_element.mako +0 -0
  148. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/grids/vue_template.mako +0 -0
  149. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/home.mako +0 -0
  150. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/master/configure.mako +0 -0
  151. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/master/create.mako +0 -0
  152. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/master/delete.mako +0 -0
  153. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/master/edit.mako +0 -0
  154. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/master/form.mako +0 -0
  155. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/master/index.mako +0 -0
  156. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/notfound.mako +0 -0
  157. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/page.mako +0 -0
  158. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/people/view_profile.mako +0 -0
  159. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/progress.mako +0 -0
  160. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/setup.mako +0 -0
  161. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/upgrade.mako +0 -0
  162. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/upgrades/configure.mako +0 -0
  163. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/upgrades/view.mako +0 -0
  164. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/templates/wutta-components.mako +0 -0
  165. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/views/__init__.py +0 -0
  166. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/views/auth.py +0 -0
  167. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/views/base.py +0 -0
  168. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/views/common.py +0 -0
  169. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/views/email.py +0 -0
  170. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/views/essential.py +0 -0
  171. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/views/people.py +0 -0
  172. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/views/progress.py +0 -0
  173. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/views/roles.py +0 -0
  174. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/views/settings.py +0 -0
  175. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/views/upgrades.py +0 -0
  176. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/src/wuttaweb/views/users.py +0 -0
  177. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tasks.py +0 -0
  178. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/__init__.py +0 -0
  179. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/cli/__init__.py +0 -0
  180. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/cli/test_webapp.py +0 -0
  181. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/db/__init__.py +0 -0
  182. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/forms/test_base.py +0 -0
  183. {wuttaweb-0.19.0/tests/forms → wuttaweb-0.19.2/tests/grids}/__init__.py +0 -0
  184. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/libcache/bb_fontawesome_svg_core.js +0 -0
  185. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/libcache/bb_free_solid_svg_icons.js +0 -0
  186. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/libcache/bb_oruga.js +0 -0
  187. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/libcache/bb_oruga_bulma.css +0 -0
  188. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/libcache/bb_oruga_bulma.js +0 -0
  189. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/libcache/bb_vue.js +0 -0
  190. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/libcache/bb_vue_fontawesome.js +0 -0
  191. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/libcache/buefy.css +0 -0
  192. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/libcache/buefy.js +0 -0
  193. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/libcache/fontawesome.js +0 -0
  194. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/libcache/vue.js +0 -0
  195. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/libcache/vue_resource.js +0 -0
  196. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/test_app.py +0 -0
  197. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/test_emails.py +0 -0
  198. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/test_helpers.py +0 -0
  199. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/test_static.py +0 -0
  200. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tests/test_subscribers.py +0 -0
  201. {wuttaweb-0.19.0/tests/grids → wuttaweb-0.19.2/tests/views}/__init__.py +0 -0
  202. {wuttaweb-0.19.0 → wuttaweb-0.19.2}/tox.ini +0 -0
@@ -5,6 +5,36 @@ All notable changes to wuttaweb will be documented in this file.
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## v0.19.2 (2025-01-07)
9
+
10
+ ### Fix
11
+
12
+ - always use prop key for default grid filters
13
+ - avoid `request.current_route_url()` for user menu
14
+ - add `scale` kwarg for `WuttaMoney` schema type, widget
15
+ - make WuttaQuantity serialize w/ app handler, remove custom widget
16
+ - bugfix for bool simple settings with default value
17
+
18
+ ## v0.19.1 (2025-01-06)
19
+
20
+ ### Fix
21
+
22
+ - improve built-in grid renderer logic
23
+ - allow session injection for ObjectRef constructor
24
+ - improve rendering for batch row status
25
+ - add basic support for row grid "view" action links
26
+ - add "xref buttons" tool panel for master view
27
+ - add WuttaQuantity schema type, widget
28
+ - remove `session` param from some form schema, widget classes
29
+ - add grid renderers for bool, currency, quantity
30
+ - use proper bulma styles for markdown content
31
+ - use span element for readonly money field widget render
32
+ - include grid filters for all column properties of model class
33
+ - use app handler to render error string, when progress fails
34
+ - add schema node type, widget for "money" (currency) fields
35
+ - exclude FK fields by default, for model forms
36
+ - fix style for header title text
37
+
8
38
  ## v0.19.0 (2024-12-23)
9
39
 
10
40
  ### Feat
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: WuttaWeb
3
- Version: 0.19.0
3
+ Version: 0.19.2
4
4
  Summary: Web App for Wutta Framework
5
5
  Project-URL: Homepage, https://wuttaproject.org/
6
6
  Project-URL: Repository, https://forgejo.wuttaproject.org/wutta/wuttaweb
@@ -39,7 +39,7 @@ Requires-Dist: pyramid-tm
39
39
  Requires-Dist: pyramid>=2
40
40
  Requires-Dist: waitress
41
41
  Requires-Dist: webhelpers2
42
- Requires-Dist: wuttjamaican[db]>=0.19.0
42
+ Requires-Dist: wuttjamaican[db]>=0.19.2
43
43
  Requires-Dist: zope-sqlalchemy>=1.5
44
44
  Provides-Extra: continuum
45
45
  Requires-Dist: wutta-continuum; extra == 'continuum'
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
6
6
 
7
7
  [project]
8
8
  name = "WuttaWeb"
9
- version = "0.19.0"
9
+ version = "0.19.2"
10
10
  description = "Web App for Wutta Framework"
11
11
  readme = "README.md"
12
12
  authors = [{name = "Lance Edgar", email = "lance@wuttaproject.org"}]
@@ -44,7 +44,7 @@ dependencies = [
44
44
  "pyramid_tm",
45
45
  "waitress",
46
46
  "WebHelpers2",
47
- "WuttJamaican[db]>=0.19.0",
47
+ "WuttJamaican[db]>=0.19.2",
48
48
  "zope.sqlalchemy>=1.5",
49
49
  ]
50
50
 
@@ -155,25 +155,75 @@ class WuttaEnum(colander.Enum):
155
155
  return widgets.SelectWidget(**kwargs)
156
156
 
157
157
 
158
+ class WuttaMoney(colander.Money):
159
+ """
160
+ Custom schema type for "money" fields.
161
+
162
+ This is a subclass of :class:`colander:colander.Money`, but uses
163
+ the custom :class:`~wuttaweb.forms.widgets.WuttaMoneyInputWidget`
164
+ by default.
165
+
166
+ :param request: Current :term:`request` object.
167
+
168
+ :param scale: If this kwarg is specified, it will be passed along
169
+ to the widget constructor.
170
+ """
171
+
172
+ def __init__(self, request, *args, **kwargs):
173
+ self.scale = kwargs.pop('scale', None)
174
+ super().__init__(*args, **kwargs)
175
+ self.request = request
176
+ self.config = self.request.wutta_config
177
+ self.app = self.config.get_app()
178
+
179
+ def widget_maker(self, **kwargs):
180
+ """ """
181
+ if self.scale:
182
+ kwargs.setdefault('scale', self.scale)
183
+ return widgets.WuttaMoneyInputWidget(self.request, **kwargs)
184
+
185
+
186
+ class WuttaQuantity(colander.Decimal):
187
+ """
188
+ Custom schema type for "quantity" fields.
189
+
190
+ This is a subclass of :class:`colander:colander.Decimal` but will
191
+ serialize values via
192
+ :meth:`~wuttjamaican:wuttjamaican.app.AppHandler.render_quantity()`.
193
+
194
+ :param request: Current :term:`request` object.
195
+ """
196
+
197
+ def __init__(self, request, *args, **kwargs):
198
+ super().__init__(*args, **kwargs)
199
+ self.request = request
200
+ self.config = self.request.wutta_config
201
+ self.app = self.config.get_app()
202
+
203
+ def serialize(self, node, appstruct):
204
+ """ """
205
+ if appstruct in (colander.null, None):
206
+ return colander.null
207
+
208
+ # nb. we render as quantity here to avoid values like 12.0000,
209
+ # so we just show value like 12 instead
210
+ return self.app.render_quantity(appstruct)
211
+
212
+
158
213
  class WuttaSet(colander.Set):
159
214
  """
160
215
  Custom schema type for :class:`python:set` fields.
161
216
 
162
- This is a subclass of :class:`colander.Set`, but adds
163
- Wutta-related params to the constructor.
217
+ This is a subclass of :class:`colander.Set`.
164
218
 
165
219
  :param request: Current :term:`request` object.
166
-
167
- :param session: Optional :term:`db session` to use instead of
168
- :class:`wuttaweb.db.sess.Session`.
169
220
  """
170
221
 
171
- def __init__(self, request, session=None):
222
+ def __init__(self, request):
172
223
  super().__init__()
173
224
  self.request = request
174
225
  self.config = self.request.wutta_config
175
226
  self.app = self.config.get_app()
176
- self.session = session or Session()
177
227
 
178
228
 
179
229
  class ObjectRef(colander.SchemaType):
@@ -209,16 +259,16 @@ class ObjectRef(colander.SchemaType):
209
259
  self,
210
260
  request,
211
261
  empty_option=None,
212
- session=None,
213
262
  *args,
214
263
  **kwargs,
215
264
  ):
265
+ # nb. allow session injection for tests
266
+ self.session = kwargs.pop('session', Session())
216
267
  super().__init__(*args, **kwargs)
217
268
  self.request = request
218
269
  self.config = self.request.wutta_config
219
270
  self.app = self.config.get_app()
220
271
  self.model_instance = None
221
- self.session = session or Session()
222
272
 
223
273
  if empty_option:
224
274
  if empty_option is True:
@@ -450,7 +500,7 @@ class RoleRefs(WuttaSet):
450
500
  :returns: Instance of
451
501
  :class:`~wuttaweb.forms.widgets.RoleRefsWidget`.
452
502
  """
453
- kwargs.setdefault('session', self.session)
503
+ session = kwargs.setdefault('session', Session())
454
504
 
455
505
  if 'values' not in kwargs:
456
506
  model = self.app.model
@@ -458,20 +508,20 @@ class RoleRefs(WuttaSet):
458
508
 
459
509
  # avoid built-ins which cannot be assigned to users
460
510
  avoid = {
461
- auth.get_role_authenticated(self.session),
462
- auth.get_role_anonymous(self.session),
511
+ auth.get_role_authenticated(session),
512
+ auth.get_role_anonymous(session),
463
513
  }
464
514
  avoid = set([role.uuid for role in avoid])
465
515
 
466
516
  # also avoid admin unless current user is root
467
517
  if not self.request.is_root:
468
- avoid.add(auth.get_role_administrator(self.session).uuid)
518
+ avoid.add(auth.get_role_administrator(session).uuid)
469
519
 
470
520
  # everything else can be (un)assigned for users
471
- roles = self.session.query(model.Role)\
472
- .filter(~model.Role.uuid.in_(avoid))\
473
- .order_by(model.Role.name)\
474
- .all()
521
+ roles = session.query(model.Role)\
522
+ .filter(~model.Role.uuid.in_(avoid))\
523
+ .order_by(model.Role.name)\
524
+ .all()
475
525
  values = [(role.uuid.hex, role.name) for role in roles]
476
526
  kwargs['values'] = values
477
527
 
@@ -496,7 +546,7 @@ class UserRefs(WuttaSet):
496
546
  :returns: Instance of
497
547
  :class:`~wuttaweb.forms.widgets.UserRefsWidget`.
498
548
  """
499
- kwargs.setdefault('session', self.session)
549
+ kwargs.setdefault('session', Session())
500
550
  return widgets.UserRefsWidget(self.request, **kwargs)
501
551
 
502
552
 
@@ -526,7 +576,7 @@ class Permissions(WuttaSet):
526
576
  :returns: Instance of
527
577
  :class:`~wuttaweb.forms.widgets.PermissionsWidget`.
528
578
  """
529
- kwargs.setdefault('session', self.session)
579
+ kwargs.setdefault('session', Session())
530
580
  kwargs.setdefault('permissions', self.permissions)
531
581
 
532
582
  if 'values' not in kwargs:
@@ -41,6 +41,7 @@ in the namespace:
41
41
  """
42
42
 
43
43
  import datetime
44
+ import decimal
44
45
  import os
45
46
 
46
47
  import colander
@@ -135,26 +136,21 @@ class WuttaCheckboxChoiceWidget(CheckboxChoiceWidget):
135
136
  Custom widget for :class:`python:set` fields.
136
137
 
137
138
  This is a subclass of
138
- :class:`deform:deform.widget.CheckboxChoiceWidget`, but adds
139
- Wutta-related params to the constructor.
139
+ :class:`deform:deform.widget.CheckboxChoiceWidget`.
140
140
 
141
141
  :param request: Current :term:`request` object.
142
142
 
143
- :param session: Optional :term:`db session` to use instead of
144
- :class:`wuttaweb.db.sess.Session`.
145
-
146
143
  It uses these Deform templates:
147
144
 
148
145
  * ``checkbox_choice``
149
146
  * ``readonly/checkbox_choice``
150
147
  """
151
148
 
152
- def __init__(self, request, session=None, *args, **kwargs):
149
+ def __init__(self, request, *args, **kwargs):
153
150
  super().__init__(*args, **kwargs)
154
151
  self.request = request
155
152
  self.config = self.request.wutta_config
156
153
  self.app = self.config.get_app()
157
- self.session = session or Session()
158
154
 
159
155
 
160
156
  class WuttaDateTimeWidget(DateTimeInputWidget):
@@ -194,6 +190,47 @@ class WuttaDateTimeWidget(DateTimeInputWidget):
194
190
  return super().serialize(field, cstruct, **kw)
195
191
 
196
192
 
193
+ class WuttaMoneyInputWidget(MoneyInputWidget):
194
+ """
195
+ Custom widget for "money" fields. This is used by default for
196
+ :class:`~wuttaweb.forms.schema.WuttaMoney` type nodes.
197
+
198
+ The main purpose of this widget is to leverage
199
+ :meth:`~wuttjamaican:wuttjamaican.app.AppHandler.render_currency()`
200
+ for the readonly display.
201
+
202
+ This is a subclass of
203
+ :class:`deform:deform.widget.MoneyInputWidget` and uses these
204
+ Deform templates:
205
+
206
+ * ``moneyinput``
207
+
208
+ :param request: Current :term:`request` object.
209
+
210
+ :param scale: If this kwarg is specified, it will be passed along
211
+ to ``render_currency()`` call.
212
+ """
213
+
214
+ def __init__(self, request, *args, **kwargs):
215
+ self.scale = kwargs.pop('scale', 2)
216
+ super().__init__(*args, **kwargs)
217
+ self.request = request
218
+ self.config = self.request.wutta_config
219
+ self.app = self.config.get_app()
220
+
221
+ def serialize(self, field, cstruct, **kw):
222
+ """ """
223
+ readonly = kw.get('readonly', self.readonly)
224
+ if readonly:
225
+ if cstruct in (colander.null, None):
226
+ return HTML.tag('span')
227
+ cstruct = decimal.Decimal(cstruct)
228
+ text = self.app.render_currency(cstruct, scale=self.scale)
229
+ return HTML.tag('span', c=[text])
230
+
231
+ return super().serialize(field, cstruct, **kw)
232
+
233
+
197
234
  class FileDownloadWidget(Widget):
198
235
  """
199
236
  Widget for use with :class:`~wuttaweb.forms.schema.FileDownload`
@@ -115,7 +115,8 @@ class Grid:
115
115
 
116
116
  Dict of column (cell) value renderer overrides.
117
117
 
118
- See also :meth:`set_renderer()`.
118
+ See also :meth:`set_renderer()` and
119
+ :meth:`set_default_renderers()`.
119
120
 
120
121
  .. attribute:: row_class
121
122
 
@@ -387,7 +388,6 @@ class Grid:
387
388
  self.key = key
388
389
  self.data = data
389
390
  self.labels = labels or {}
390
- self.renderers = renderers or {}
391
391
  self.row_class = row_class
392
392
  self.actions = actions or []
393
393
  self.linked_columns = linked_columns or []
@@ -397,6 +397,10 @@ class Grid:
397
397
  self.app = self.config.get_app()
398
398
 
399
399
  self.set_columns(columns or self.get_columns())
400
+ self.renderers = {}
401
+ if renderers:
402
+ for key, val in renderers.items():
403
+ self.set_renderer(key, val)
400
404
  self.set_default_renderers()
401
405
  self.set_tools(tools)
402
406
 
@@ -591,8 +595,29 @@ class Grid:
591
595
  grid = Grid(request, columns=['foo', 'bar'])
592
596
  grid.set_renderer('foo', render_foo)
593
597
 
598
+ For convenience, in lieu of a renderer callable, you may
599
+ specify one of the following strings, which will be
600
+ interpreted as a built-in renderer callable, as shown below:
601
+
602
+ * ``'batch_id'`` -> :meth:`render_batch_id()`
603
+ * ``'boolean'`` -> :meth:`render_boolean()`
604
+ * ``'currency'`` -> :meth:`render_currency()`
605
+ * ``'datetime'`` -> :meth:`render_datetime()`
606
+ * ``'quantity'`` -> :meth:`render_quantity()`
607
+
594
608
  Renderer overrides are tracked via :attr:`renderers`.
595
609
  """
610
+ builtins = {
611
+ 'batch_id': self.render_batch_id,
612
+ 'boolean': self.render_boolean,
613
+ 'currency': self.render_currency,
614
+ 'datetime': self.render_datetime,
615
+ 'quantity': self.render_quantity,
616
+ }
617
+
618
+ if renderer in builtins:
619
+ renderer = builtins[renderer]
620
+
596
621
  if kwargs:
597
622
  renderer = functools.partial(renderer, **kwargs)
598
623
  self.renderers[key] = renderer
@@ -601,15 +626,18 @@ class Grid:
601
626
  """
602
627
  Set default column value renderers, where applicable.
603
628
 
604
- This will add new entries to :attr:`renderers` for columns
605
- whose data type implies a default renderer should be used.
606
- This is generally only possible if :attr:`model_class` is set
607
- to a valid SQLAlchemy mapped class.
629
+ This is called automatically from the class constructor. It
630
+ will add new entries to :attr:`renderers` for columns whose
631
+ data type implies a default renderer. This is only possible
632
+ if :attr:`model_class` is set to a SQLAlchemy mapped class.
633
+
634
+ This only looks for a couple of data types, and configures as
635
+ follows:
608
636
 
609
- This (for now?) only looks for
610
- :class:`sqlalchemy:sqlalchemy.types.DateTime` columns and if
611
- any are found, they are configured to use
612
- :meth:`render_datetime()`.
637
+ * :class:`sqlalchemy:sqlalchemy.types.Boolean` ->
638
+ :meth:`render_boolean()`
639
+ * :class:`sqlalchemy:sqlalchemy.types.DateTime` ->
640
+ :meth:`render_datetime()`
613
641
  """
614
642
  if not self.model_class:
615
643
  return
@@ -625,6 +653,8 @@ class Grid:
625
653
  column = prop.columns[0]
626
654
  if isinstance(column.type, sa.DateTime):
627
655
  self.set_renderer(key, self.render_datetime)
656
+ elif isinstance(column.type, sa.Boolean):
657
+ self.set_renderer(key, self.render_boolean)
628
658
 
629
659
  def set_link(self, key, link=True):
630
660
  """
@@ -1116,19 +1146,29 @@ class Grid:
1116
1146
  filters = filters or {}
1117
1147
 
1118
1148
  if self.model_class:
1119
- # TODO: i tried using self.get_model_columns() here but in
1120
- # many cases that will be too aggressive. however it is
1121
- # often the case that the *grid* columns are a subset of
1122
- # the unerlying *table* columns. so until a better way
1123
- # is found, we choose "too few" instead of "too many"
1124
- # filters here. surely must improve it at some point.
1125
- for key in self.columns:
1126
- if key in filters:
1127
- continue
1128
- prop = getattr(self.model_class, key, None)
1129
- if (prop and hasattr(prop, 'property')
1130
- and isinstance(prop.property, orm.ColumnProperty)):
1131
- filters[prop.key] = self.make_filter(prop)
1149
+
1150
+ # nb. i have found this confusing for some reason. some
1151
+ # things i've tried so far include:
1152
+ #
1153
+ # i first tried self.get_model_columns() but my notes say
1154
+ # that was too aggressive in many cases.
1155
+ #
1156
+ # then i tried using the *subset* of self.columns, just
1157
+ # the ones which correspond to a property on the model
1158
+ # class. but sometimes that skips filters we need.
1159
+ #
1160
+ # then i tried get_columns() from sa-utils to give the
1161
+ # "true" column list, but that fails when the underlying
1162
+ # column has different name than the prop/attr key.
1163
+ #
1164
+ # so now, we are looking directly at the sa mapper, for
1165
+ # all column attrs and then using the prop key.
1166
+
1167
+ inspector = sa.inspect(self.model_class)
1168
+ for prop in inspector.column_attrs:
1169
+ if prop.key not in filters:
1170
+ attr = getattr(self.model_class, prop.key)
1171
+ filters[prop.key] = self.make_filter(attr)
1132
1172
 
1133
1173
  return filters
1134
1174
 
@@ -1755,23 +1795,80 @@ class Grid:
1755
1795
  # rendering methods
1756
1796
  ##############################
1757
1797
 
1798
+ def render_batch_id(self, obj, key, value):
1799
+ """
1800
+ Column renderer for batch ID values.
1801
+
1802
+ This is not used automatically but you can use it explicitly::
1803
+
1804
+ grid.set_renderer('foo', 'batch_id')
1805
+ """
1806
+ if value is None:
1807
+ return ""
1808
+
1809
+ batch_id = int(value)
1810
+ return f'{batch_id:08d}'
1811
+
1812
+ def render_boolean(self, obj, key, value):
1813
+ """
1814
+ Column renderer for boolean values.
1815
+
1816
+ This calls
1817
+ :meth:`~wuttjamaican:wuttjamaican.app.AppHandler.render_boolean()`
1818
+ for the return value.
1819
+
1820
+ This may be used automatically per
1821
+ :meth:`set_default_renderers()` or you can use it explicitly::
1822
+
1823
+ grid.set_renderer('foo', grid.render_boolean)
1824
+ """
1825
+ return self.app.render_boolean(value)
1826
+
1827
+ def render_currency(self, obj, key, value, **kwargs):
1828
+ """
1829
+ Column renderer for currency values.
1830
+
1831
+ This calls
1832
+ :meth:`~wuttjamaican:wuttjamaican.app.AppHandler.render_currency()`
1833
+ for the return value.
1834
+
1835
+ This is not used automatically but you can use it explicitly::
1836
+
1837
+ grid.set_renderer('foo', 'currency')
1838
+ grid.set_renderer('foo', 'currency', scale=4)
1839
+ """
1840
+ return self.app.render_currency(value, **kwargs)
1841
+
1758
1842
  def render_datetime(self, obj, key, value):
1759
1843
  """
1760
- Default cell value renderer for
1761
- :class:`sqlalchemy:sqlalchemy.types.DateTime` columns, which
1762
- calls
1844
+ Column renderer for :class:`python:datetime.datetime` values.
1845
+
1846
+ This calls
1763
1847
  :meth:`~wuttjamaican:wuttjamaican.app.AppHandler.render_datetime()`
1764
1848
  for the return value.
1765
1849
 
1766
1850
  This may be used automatically per
1767
- :meth:`set_default_renderers()` or you can use it explicitly
1768
- for any :class:`python:datetime.datetime` column with::
1851
+ :meth:`set_default_renderers()` or you can use it explicitly::
1769
1852
 
1770
1853
  grid.set_renderer('foo', grid.render_datetime)
1771
1854
  """
1772
1855
  dt = getattr(obj, key)
1773
1856
  return self.app.render_datetime(dt)
1774
1857
 
1858
+ def render_quantity(self, obj, key, value):
1859
+ """
1860
+ Column renderer for quantity values.
1861
+
1862
+ This calls
1863
+ :meth:`~wuttjamaican:wuttjamaican.app.AppHandler.render_quantity()`
1864
+ for the return value.
1865
+
1866
+ This is not used automatically but you can use it explicitly::
1867
+
1868
+ grid.set_renderer('foo', grid.render_quantity)
1869
+ """
1870
+ return self.app.render_quantity(value)
1871
+
1775
1872
  def render_table_element(
1776
1873
  self,
1777
1874
  form=None,
@@ -92,6 +92,9 @@ class SessionProgress(ProgressBase):
92
92
  """
93
93
 
94
94
  def __init__(self, request, key, success_msg=None, success_url=None, error_url=None):
95
+ self.request = request
96
+ self.config = self.request.wutta_config
97
+ self.app = self.config.get_app()
95
98
  self.key = key
96
99
  self.success_msg = success_msg
97
100
  self.success_url = success_url
@@ -137,7 +140,7 @@ class SessionProgress(ProgressBase):
137
140
  """
138
141
  self.session.load()
139
142
  self.session['error'] = True
140
- self.session['error_msg'] = str(error)
143
+ self.session['error_msg'] = self.app.render_error(error)
141
144
  self.session['error_url'] = error_url or self.error_url
142
145
  self.session.save()
143
146
 
@@ -155,7 +155,7 @@
155
155
  }
156
156
 
157
157
  #content-title h1 {
158
- max-width: 50%;
158
+ max-width: 80%;
159
159
  overflow: hidden;
160
160
  padding-left: 0.5rem;
161
161
  text-overflow: ellipsis;
@@ -659,7 +659,7 @@
659
659
  % if request.is_root:
660
660
  ${h.form(url('stop_root'), ref='stopBeingRootForm')}
661
661
  ${h.csrf_token(request)}
662
- <input type="hidden" name="referrer" value="${request.current_route_url()}" />
662
+ <input type="hidden" name="referrer" value="${request.url}" />
663
663
  <a @click="stopBeingRoot()"
664
664
  class="navbar-item has-background-danger has-text-white">
665
665
  Stop being root
@@ -1,19 +1,6 @@
1
1
  ## -*- coding: utf-8; -*-
2
2
  <%inherit file="/master/view.mako" />
3
3
 
4
- <%def name="extra_styles()">
5
- ${parent.extra_styles()}
6
- <style>
7
-
8
- ## TODO: should we do something like this site-wide?
9
- ## (so far this is the only place we use markdown)
10
- .markdown p {
11
- margin-bottom: 1.5rem;
12
- }
13
-
14
- </style>
15
- </%def>
16
-
17
4
  <%def name="tool_panels()">
18
5
  ${parent.tool_panels()}
19
6
  ${self.tool_panel_execution()}
@@ -65,7 +52,7 @@
65
52
  <p class="block has-text-weight-bold">
66
53
  What will happen when this batch is executed?
67
54
  </p>
68
- <div class="markdown">
55
+ <div class="content">
69
56
  ${execution_described|n}
70
57
  </div>
71
58
  ${h.form(master.get_action_url('execute', batch), ref='executeForm')}
@@ -33,6 +33,21 @@
33
33
  % endif
34
34
  </%def>
35
35
 
36
+ <%def name="tool_panels()">
37
+ ${parent.tool_panels()}
38
+ ${self.tool_panel_xref()}
39
+ </%def>
40
+
41
+ <%def name="tool_panel_xref()">
42
+ % if xref_buttons:
43
+ <wutta-tool-panel heading="Cross-Reference">
44
+ % for button in xref_buttons:
45
+ ${button}
46
+ % endfor
47
+ </wutta-tool-panel>
48
+ % endif
49
+ </%def>
50
+
36
51
  <%def name="render_vue_templates()">
37
52
  ${parent.render_vue_templates()}
38
53
  % if master.has_rows: