WuttaWeb 0.27.0__tar.gz → 0.27.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 (249) hide show
  1. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/CHANGELOG.md +29 -0
  2. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/PKG-INFO +2 -2
  3. wuttaweb-0.27.2/README.md +6 -0
  4. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/index.rst +1 -1
  5. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/pyproject.toml +1 -1
  6. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/code-templates/new-table.mako +11 -15
  7. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/grids/base.py +37 -10
  8. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/subscribers.py +2 -0
  9. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/appinfo/index.mako +27 -28
  10. wuttaweb-0.27.2/src/wuttaweb/templates/batch/view.mako +113 -0
  11. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/grids/table_element.mako +2 -0
  12. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/master/view.mako +13 -2
  13. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/master/view_version.mako +11 -0
  14. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/tables/app/create.mako +2 -2
  15. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/views/auth.py +12 -4
  16. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/views/batch.py +7 -3
  17. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/views/common.py +20 -1
  18. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/views/master.py +13 -1
  19. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/views/people.py +3 -1
  20. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/grids/test_base.py +33 -3
  21. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/test_batch.py +1 -0
  22. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/test_people.py +5 -4
  23. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/test_tables.py +1 -1
  24. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tox.ini +1 -1
  25. wuttaweb-0.27.0/README.md +0 -6
  26. wuttaweb-0.27.0/src/wuttaweb/templates/batch/view.mako +0 -111
  27. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/.gitignore +0 -0
  28. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/.hgignore +0 -0
  29. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/.pylintrc +0 -0
  30. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/COPYING.txt +0 -0
  31. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/Makefile +0 -0
  32. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/_static/.keepme +0 -0
  33. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.app.rst +0 -0
  34. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.auth.rst +0 -0
  35. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.cli.rst +0 -0
  36. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.cli.webapp.rst +0 -0
  37. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.conf.rst +0 -0
  38. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.db.continuum.rst +0 -0
  39. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.db.rst +0 -0
  40. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.db.sess.rst +0 -0
  41. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.diffs.rst +0 -0
  42. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.emails.rst +0 -0
  43. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.forms.base.rst +0 -0
  44. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.forms.rst +0 -0
  45. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.forms.schema.rst +0 -0
  46. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.forms.widgets.rst +0 -0
  47. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.grids.base.rst +0 -0
  48. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.grids.filters.rst +0 -0
  49. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.grids.rst +0 -0
  50. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.handler.rst +0 -0
  51. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.helpers.rst +0 -0
  52. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.menus.rst +0 -0
  53. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.progress.rst +0 -0
  54. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.rst +0 -0
  55. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.static.rst +0 -0
  56. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.subscribers.rst +0 -0
  57. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.util.rst +0 -0
  58. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.views.alembic.rst +0 -0
  59. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.views.auth.rst +0 -0
  60. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.views.base.rst +0 -0
  61. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.views.batch.rst +0 -0
  62. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.views.common.rst +0 -0
  63. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.views.email.rst +0 -0
  64. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.views.essential.rst +0 -0
  65. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.views.master.rst +0 -0
  66. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.views.people.rst +0 -0
  67. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.views.progress.rst +0 -0
  68. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.views.reports.rst +0 -0
  69. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.views.roles.rst +0 -0
  70. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.views.rst +0 -0
  71. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.views.settings.rst +0 -0
  72. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.views.tables.rst +0 -0
  73. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.views.upgrades.rst +0 -0
  74. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.views.users.rst +0 -0
  75. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/api/wuttaweb.views.views.rst +0 -0
  76. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/conf.py +0 -0
  77. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/glossary.rst +0 -0
  78. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/make.bat +0 -0
  79. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/narr/cli/builtin.rst +0 -0
  80. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/narr/cli/index.rst +0 -0
  81. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/narr/templates/base.rst +0 -0
  82. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/narr/templates/index.rst +0 -0
  83. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/narr/templates/lookup.rst +0 -0
  84. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/docs/narr/templates/overview.rst +0 -0
  85. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/__init__.py +0 -0
  86. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/_version.py +0 -0
  87. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/app.py +0 -0
  88. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/auth.py +0 -0
  89. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/cli/__init__.py +0 -0
  90. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/cli/webapp.py +0 -0
  91. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/code-templates/new-master-view.mako +0 -0
  92. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/conf.py +0 -0
  93. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/db/__init__.py +0 -0
  94. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/db/continuum.py +0 -0
  95. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/db/sess.py +0 -0
  96. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/diffs.py +0 -0
  97. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/email-templates/feedback.html.mako +0 -0
  98. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/email-templates/feedback.txt.mako +0 -0
  99. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/emails.py +0 -0
  100. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/forms/__init__.py +0 -0
  101. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/forms/base.py +0 -0
  102. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/forms/schema.py +0 -0
  103. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/forms/widgets.py +0 -0
  104. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/grids/__init__.py +0 -0
  105. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/grids/filters.py +0 -0
  106. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/handler.py +0 -0
  107. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/helpers.py +0 -0
  108. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/menus.py +0 -0
  109. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/progress.py +0 -0
  110. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/static/__init__.py +0 -0
  111. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/static/img/favicon.ico +0 -0
  112. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/static/img/logo.png +0 -0
  113. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/static/img/testing.png +0 -0
  114. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/alembic/dashboard.mako +0 -0
  115. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/alembic/migrations/configure.mako +0 -0
  116. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/alembic/migrations/create.mako +0 -0
  117. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/alembic/migrations/index.mako +0 -0
  118. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/alembic/migrations/view.mako +0 -0
  119. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/appinfo/configure.mako +0 -0
  120. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/auth/change_password.mako +0 -0
  121. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/auth/login.mako +0 -0
  122. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/base.mako +0 -0
  123. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/base_meta.mako +0 -0
  124. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/configure.mako +0 -0
  125. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/checkbox.pt +0 -0
  126. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/checkbox_choice.pt +0 -0
  127. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/checked_password.pt +0 -0
  128. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/dateinput.pt +0 -0
  129. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/datetimeinput.pt +0 -0
  130. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/moneyinput.pt +0 -0
  131. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/password.pt +0 -0
  132. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/permissions.pt +0 -0
  133. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/readonly/checkbox.pt +0 -0
  134. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/readonly/email_recips.pt +0 -0
  135. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/readonly/filedownload.pt +0 -0
  136. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/readonly/notes.pt +0 -0
  137. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/readonly/objectref.pt +0 -0
  138. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/readonly/permissions.pt +0 -0
  139. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/readonly/rolerefs.pt +0 -0
  140. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/select.pt +0 -0
  141. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/textarea.pt +0 -0
  142. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/textinput.pt +0 -0
  143. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/deform/wutta_checked_password.pt +0 -0
  144. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/diff.mako +0 -0
  145. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/email/settings/view.mako +0 -0
  146. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/forbidden.mako +0 -0
  147. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/form.mako +0 -0
  148. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/forms/vue_buttons.mako +0 -0
  149. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/forms/vue_fields.mako +0 -0
  150. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/forms/vue_template.mako +0 -0
  151. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/grids/vue_template.mako +0 -0
  152. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/home.mako +0 -0
  153. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/master/configure.mako +0 -0
  154. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/master/create.mako +0 -0
  155. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/master/create_row.mako +0 -0
  156. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/master/delete.mako +0 -0
  157. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/master/edit.mako +0 -0
  158. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/master/form.mako +0 -0
  159. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/master/index.mako +0 -0
  160. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/master/view_versions.mako +0 -0
  161. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/notfound.mako +0 -0
  162. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/page.mako +0 -0
  163. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/people/view_profile.mako +0 -0
  164. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/progress.mako +0 -0
  165. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/reports/view.mako +0 -0
  166. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/setup.mako +0 -0
  167. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/tables/app/index.mako +0 -0
  168. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/themes/butterfly/base.mako +0 -0
  169. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/themes/butterfly/buefy-components.mako +0 -0
  170. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/themes/butterfly/buefy-plugin.mako +0 -0
  171. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/themes/butterfly/http-plugin.mako +0 -0
  172. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/upgrade.mako +0 -0
  173. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/upgrades/configure.mako +0 -0
  174. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/upgrades/index.mako +0 -0
  175. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/upgrades/view.mako +0 -0
  176. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/users/view.mako +0 -0
  177. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/views/master/configure.mako +0 -0
  178. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/views/master/create.mako +0 -0
  179. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/views/master/index.mako +0 -0
  180. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/templates/wutta-components.mako +0 -0
  181. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/testing.py +0 -0
  182. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/util.py +0 -0
  183. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/views/__init__.py +0 -0
  184. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/views/alembic.py +0 -0
  185. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/views/base.py +0 -0
  186. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/views/email.py +0 -0
  187. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/views/essential.py +0 -0
  188. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/views/progress.py +0 -0
  189. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/views/reports.py +0 -0
  190. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/views/roles.py +0 -0
  191. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/views/settings.py +0 -0
  192. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/views/tables.py +0 -0
  193. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/views/upgrades.py +0 -0
  194. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/views/users.py +0 -0
  195. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/src/wuttaweb/views/views.py +0 -0
  196. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tasks.py +0 -0
  197. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/__init__.py +0 -0
  198. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/cli/__init__.py +0 -0
  199. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/cli/test_webapp.py +0 -0
  200. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/db/__init__.py +0 -0
  201. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/db/test_continuum.py +0 -0
  202. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/forms/main_template.mako +0 -0
  203. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/forms/main_template_with_fields.mako +0 -0
  204. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/forms/test_base.py +0 -0
  205. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/forms/test_schema.py +0 -0
  206. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/forms/test_widgets.py +0 -0
  207. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/grids/__init__.py +0 -0
  208. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/grids/test_filters.py +0 -0
  209. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/libcache/bb_fontawesome_svg_core.js +0 -0
  210. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/libcache/bb_free_solid_svg_icons.js +0 -0
  211. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/libcache/bb_oruga.js +0 -0
  212. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/libcache/bb_oruga_bulma.css +0 -0
  213. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/libcache/bb_oruga_bulma.js +0 -0
  214. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/libcache/bb_vue.js +0 -0
  215. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/libcache/bb_vue_fontawesome.js +0 -0
  216. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/libcache/buefy.css +0 -0
  217. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/libcache/buefy.js +0 -0
  218. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/libcache/fontawesome.js +0 -0
  219. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/libcache/vue.js +0 -0
  220. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/libcache/vue_resource.js +0 -0
  221. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/test_app.py +0 -0
  222. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/test_auth.py +0 -0
  223. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/test_conf.py +0 -0
  224. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/test_diffs.py +0 -0
  225. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/test_emails.py +0 -0
  226. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/test_handler.py +0 -0
  227. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/test_helpers.py +0 -0
  228. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/test_menus.py +0 -0
  229. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/test_progress.py +0 -0
  230. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/test_static.py +0 -0
  231. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/test_subscribers.py +0 -0
  232. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/test_util.py +0 -0
  233. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/util.py +0 -0
  234. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/__init__.py +0 -0
  235. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/test___init__.py +0 -0
  236. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/test_alembic.py +0 -0
  237. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/test_auth.py +0 -0
  238. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/test_base.py +0 -0
  239. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/test_common.py +0 -0
  240. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/test_email.py +0 -0
  241. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/test_essential.py +0 -0
  242. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/test_master.py +0 -0
  243. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/test_progress.py +0 -0
  244. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/test_reports.py +0 -0
  245. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/test_roles.py +0 -0
  246. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/test_settings.py +0 -0
  247. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/test_upgrades.py +0 -0
  248. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/test_users.py +0 -0
  249. {wuttaweb-0.27.0 → wuttaweb-0.27.2}/tests/views/test_views.py +0 -0
@@ -5,6 +5,35 @@ 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.27.2 (2026-02-04)
9
+
10
+ ### Fix
11
+
12
+ - fallback to dict logic for grid render date/time
13
+ - add dedicated `authenticate_user()` method for auth view
14
+ - increase default width for read-only form views
15
+ - add `hoverable` and `narrowed` for all `<b-table>` elements
16
+ - show users grid when deleting a Person
17
+ - add `model` and `enum` to global template rendering context
18
+ - ensure grid action icon+label do not wrap
19
+
20
+ ## v0.27.1 (2026-01-03)
21
+
22
+ ### Fix
23
+
24
+ - add separate def for middle buttons on App Info page
25
+ - expose version history for site admin in default setup
26
+ - only show execution panel if batch view supports it
27
+ - remove the Users field for create/edit Person
28
+ - only show "create row" button if batch view supports it
29
+ - show proper batch status text, from enum
30
+ - use wutta hint from model, for master view title
31
+ - accept dict instead of true enum, for `Grid.set_enum()`
32
+ - improve FK handling in generated model class code
33
+ - use custom UUID type when generating model class code for FK
34
+ - fix spacing style when viewing object with row grid
35
+ - grant access to alembic, tables, master view admin for new apps
36
+
8
37
  ## v0.27.0 (2025-12-31)
9
38
 
10
39
  ### Feat
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: WuttaWeb
3
- Version: 0.27.0
3
+ Version: 0.27.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
@@ -61,4 +61,4 @@ Description-Content-Type: text/markdown
61
61
 
62
62
  Web app for Wutta Framework
63
63
 
64
- See docs at https://rattailproject.org/docs/wuttaweb/
64
+ See docs at https://docs.wuttaproject.org/wuttaweb/
@@ -0,0 +1,6 @@
1
+
2
+ # WuttaWeb
3
+
4
+ Web app for Wutta Framework
5
+
6
+ See docs at https://docs.wuttaproject.org/wuttaweb/
@@ -9,7 +9,7 @@ It uses traditional server-side rendering with VueJS on the front-end.
9
9
  Good documentation and 100% `test coverage`_ are priorities for this
10
10
  project.
11
11
 
12
- .. _test coverage: https://buildbot.rattailproject.org/coverage/wuttaweb/
12
+ .. _test coverage: https://buildbot.wuttaproject.org/coverage/wuttaweb/
13
13
 
14
14
  .. image:: https://img.shields.io/badge/linting-pylint-yellowgreen
15
15
  :target: https://github.com/pylint-dev/pylint
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
6
6
 
7
7
  [project]
8
8
  name = "WuttaWeb"
9
- version = "0.27.0"
9
+ version = "0.27.2"
10
10
  description = "Web App for Wutta Framework"
11
11
  readme = "README.md"
12
12
  authors = [{name = "Lance Edgar", email = "lance@wuttaproject.org"}]
@@ -15,16 +15,6 @@ class ${model_name}(model.Base):
15
15
  ${description}
16
16
  """
17
17
  __tablename__ = "${table_name}"
18
- % if any([c["data_type"]["type"] == "_fk_uuid_" for c in columns]):
19
- __table_args__ = (
20
- % for column in columns:
21
- % if column["data_type"]["type"] == "_fk_uuid_":
22
- sa.ForeignKeyConstraint(["${column['name']}"], ["${column['data_type']['reference']}.uuid"],
23
- name="${table_name}_fk_${column['data_type']['reference']}"),
24
- % endif
25
- % endfor
26
- )
27
- % endif
28
18
  % if versioned:
29
19
  % if all([c["versioned"] for c in columns]):
30
20
  __versioned__ = {}
@@ -48,17 +38,23 @@ class ${model_name}(model.Base):
48
38
 
49
39
  % if column["name"] == "uuid":
50
40
  uuid = model.uuid_column()
51
- % else:
52
- ${column["name"]} = sa.Column(${column["formatted_data_type"]}, nullable=${column["nullable"]}, doc="""
53
- ${column["description"] or ""}
54
- """)
55
- % if column["data_type"]["type"] == "_fk_uuid_" and column["relationship"]:
41
+ % elif column["data_type"]["type"] == "_fk_uuid_":
42
+ ${column["name"]} = model.uuid_fk_column("${column['data_type']['reference']}.uuid",
43
+ nullable=${column["nullable"]})
44
+ % if column["relationship"]:
56
45
  ${column["relationship"]["name"]} = orm.relationship(
57
46
  "${column['relationship']['reference_model']}",
58
47
  doc="""
59
48
  ${column["description"] or ""}
60
49
  """)
61
50
  % endif
51
+ % else:
52
+ ${column["name"]} = sa.Column(
53
+ ${column["formatted_data_type"]},
54
+ nullable=${column["nullable"]},
55
+ doc="""
56
+ ${column["description"] or ""}
57
+ """)
62
58
  % endif
63
59
  % endfor
64
60
 
@@ -2,7 +2,7 @@
2
2
  ################################################################################
3
3
  #
4
4
  # wuttaweb -- Web App for Wutta Framework
5
- # Copyright © 2024-2025 Lance Edgar
5
+ # Copyright © 2024-2026 Lance Edgar
6
6
  #
7
7
  # This file is part of Wutta Framework.
8
8
  #
@@ -30,6 +30,12 @@ import logging
30
30
  import warnings
31
31
  from collections import namedtuple, OrderedDict
32
32
 
33
+ try:
34
+ from enum import EnumType
35
+ except ImportError: # pragma: no cover
36
+ # nb. python < 3.11
37
+ from enum import EnumMeta as EnumType
38
+
33
39
  import sqlalchemy as sa
34
40
  from sqlalchemy import orm
35
41
 
@@ -763,7 +769,7 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth
763
769
 
764
770
  :param key: Name of column.
765
771
 
766
- :param enum: Instance of :class:`python:enum.Enum`.
772
+ :param enum: Instance of :class:`python:enum.Enum`, or a dict.
767
773
  """
768
774
  self.enums[key] = enum
769
775
  self.set_renderer(key, self.render_enum, enum=enum)
@@ -2024,7 +2030,10 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth
2024
2030
 
2025
2031
  grid.set_renderer('foo', 'date')
2026
2032
  """
2027
- dt = getattr(obj, key)
2033
+ try:
2034
+ dt = getattr(obj, key)
2035
+ except AttributeError:
2036
+ dt = obj[key]
2028
2037
  return self.app.render_date(dt)
2029
2038
 
2030
2039
  def render_datetime(self, obj, key, value): # pylint: disable=unused-argument
@@ -2040,7 +2049,10 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth
2040
2049
 
2041
2050
  grid.set_renderer('foo', 'datetime')
2042
2051
  """
2043
- dt = getattr(obj, key)
2052
+ try:
2053
+ dt = getattr(obj, key)
2054
+ except AttributeError:
2055
+ dt = obj[key]
2044
2056
  return self.app.render_datetime(dt, html=True)
2045
2057
 
2046
2058
  def render_enum(self, obj, key, value, enum=None):
@@ -2050,7 +2062,7 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth
2050
2062
  See also :meth:`set_enum()`.
2051
2063
 
2052
2064
  :param enum: Enum class for the field. This should be an
2053
- instance of :class:`~python:enum.Enum`.
2065
+ instance of :class:`~python:enum.Enum` or else a dict.
2054
2066
 
2055
2067
  To use this feature for your grid::
2056
2068
 
@@ -2061,12 +2073,26 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth
2061
2073
  TWO = 2
2062
2074
  THREE = 3
2063
2075
 
2064
- grid.set_enum('my_enum_field', MyEnum)
2076
+ grid.set_enum("my_enum_field", MyEnum)
2077
+
2078
+ Or, perhaps more common::
2079
+
2080
+ myenum = {
2081
+ 1: "ONE",
2082
+ 2: "TWO",
2083
+ 3: "THREE",
2084
+ }
2085
+
2086
+ grid.set_enum("my_enum_field", myenum)
2065
2087
  """
2066
2088
  if enum:
2067
- raw_value = obj[key]
2068
- if raw_value:
2069
- return raw_value.value
2089
+
2090
+ if isinstance(enum, EnumType):
2091
+ if raw_value := obj[key]:
2092
+ return raw_value.value
2093
+
2094
+ if isinstance(enum, dict):
2095
+ return enum.get(value, value)
2070
2096
 
2071
2097
  return value
2072
2098
 
@@ -2584,9 +2610,10 @@ class GridAction: # pylint: disable=too-many-instance-attributes
2584
2610
  """
2585
2611
  html = [
2586
2612
  self.render_icon(),
2613
+ HTML.literal("&nbsp;"),
2587
2614
  self.render_label(),
2588
2615
  ]
2589
- return HTML.literal(" ").join(html)
2616
+ return HTML.tag("span", c=html, style="white-space: nowrap;")
2590
2617
 
2591
2618
  def render_icon(self):
2592
2619
  """
@@ -402,6 +402,8 @@ def before_render(event):
402
402
  context = event
403
403
  context["config"] = config
404
404
  context["app"] = app
405
+ context["model"] = app.model
406
+ context["enum"] = app.enum
405
407
  context["web"] = web
406
408
  context["h"] = helpers
407
409
  context["url"] = request.route_url
@@ -36,31 +36,7 @@
36
36
  </nav>
37
37
 
38
38
  <div class="buttons">
39
-
40
- % if request.has_perm("master_views.list"):
41
- <wutta-button type="is-primary"
42
- tag="a" href="${url('master_views')}"
43
- icon-left="eye"
44
- label="Master Views"
45
- once />
46
- % endif
47
-
48
- % if request.has_perm("app_tables.list"):
49
- <wutta-button type="is-primary"
50
- tag="a" href="${url('app_tables')}"
51
- icon-left="table"
52
- label="App Tables"
53
- once />
54
- % endif
55
-
56
- % if request.has_perm("alembic.dashboard"):
57
- <wutta-button type="is-primary"
58
- tag="a" href="${url('alembic.dashboard')}"
59
- icon-left="forward"
60
- label="Alembic Dashboard"
61
- once />
62
- % endif
63
-
39
+ ${self.middle_buttons()}
64
40
  </div>
65
41
 
66
42
  <nav class="panel">
@@ -123,6 +99,32 @@
123
99
 
124
100
  </%def>
125
101
 
102
+ <%def name="middle_buttons()">
103
+ % if request.has_perm("master_views.list"):
104
+ <wutta-button type="is-primary"
105
+ tag="a" href="${url('master_views')}"
106
+ icon-left="eye"
107
+ label="Master Views"
108
+ once />
109
+ % endif
110
+
111
+ % if request.has_perm("app_tables.list"):
112
+ <wutta-button type="is-primary"
113
+ tag="a" href="${url('app_tables')}"
114
+ icon-left="table"
115
+ label="App Tables"
116
+ once />
117
+ % endif
118
+
119
+ % if request.has_perm("alembic.dashboard"):
120
+ <wutta-button type="is-primary"
121
+ tag="a" href="${url('alembic.dashboard')}"
122
+ icon-left="forward"
123
+ label="Alembic Dashboard"
124
+ once />
125
+ % endif
126
+ </%def>
127
+
126
128
  <%def name="modify_vue_vars()">
127
129
  ${parent.modify_vue_vars()}
128
130
  <script>
@@ -135,6 +137,3 @@
135
137
 
136
138
  </script>
137
139
  </%def>
138
-
139
-
140
- ${parent.body()}
@@ -0,0 +1,113 @@
1
+ ## -*- coding: utf-8; -*-
2
+ <%inherit file="/master/view.mako" />
3
+
4
+ <%def name="tool_panels()">
5
+ ${parent.tool_panels()}
6
+ ${self.tool_panel_execution()}
7
+ </%def>
8
+
9
+ <%def name="tool_panel_execution()">
10
+ % if master.executable:
11
+ <wutta-tool-panel heading="Execution">
12
+ % if batch.executed:
13
+ <b-notification :closable="false">
14
+ <p class="block">
15
+ Batch was executed<br />
16
+ ${app.render_time_ago(batch.executed)}<br />
17
+ by ${batch.executed_by}
18
+ </p>
19
+ </b-notification>
20
+ % elif why_not_execute:
21
+ <b-notification type="is-warning" :closable="false">
22
+ <p class="block">
23
+ Batch cannot be executed:
24
+ </p>
25
+ <p class="block">
26
+ ${why_not_execute}
27
+ </p>
28
+ </b-notification>
29
+ % else:
30
+ % if master.has_perm('execute'):
31
+ <b-notification type="is-success" :closable="false">
32
+ <p class="block">
33
+ Batch can be executed
34
+ </p>
35
+ <b-button type="is-primary"
36
+ @click="executeInit()"
37
+ icon-pack="fas"
38
+ icon-left="arrow-circle-right">
39
+ Execute Batch
40
+ </b-button>
41
+
42
+ <b-modal has-modal-card
43
+ :active.sync="executeShowDialog">
44
+ <div class="modal-card">
45
+
46
+ <header class="modal-card-head">
47
+ <p class="modal-card-title">Execute ${model_title}</p>
48
+ </header>
49
+
50
+ ## TODO: forcing black text b/c of b-notification
51
+ ## wrapping button, which has white text
52
+ <section class="modal-card-body has-text-black">
53
+ <p class="block has-text-weight-bold">
54
+ What will happen when this batch is executed?
55
+ </p>
56
+ <div class="content">
57
+ ${execution_described|n}
58
+ </div>
59
+ ${h.form(master.get_action_url('execute', batch), ref='executeForm')}
60
+ ${h.csrf_token(request)}
61
+ ${h.end_form()}
62
+ </section>
63
+
64
+ <footer class="modal-card-foot">
65
+ <b-button @click="executeShowDialog = false">
66
+ Cancel
67
+ </b-button>
68
+ <b-button type="is-primary"
69
+ @click="executeSubmit()"
70
+ icon-pack="fas"
71
+ icon-left="arrow-circle-right"
72
+ :disabled="executeSubmitting">
73
+ {{ executeSubmitting ? "Working, please wait..." : "Execute Batch" }}
74
+ </b-button>
75
+ </footer>
76
+
77
+ </div>
78
+ </b-modal>
79
+ </b-notification>
80
+
81
+ % else:
82
+ <b-notification type="is-warning" :closable="false">
83
+ <p class="block">
84
+ Batch may be executed,<br />
85
+ but you do not have permission.
86
+ </p>
87
+ </b-notification>
88
+ % endif
89
+ % endif
90
+ </wutta-tool-panel>
91
+ % endif
92
+ </%def>
93
+
94
+ <%def name="modify_vue_vars()">
95
+ ${parent.modify_vue_vars()}
96
+ % if not batch.executed and not why_not_execute and master.has_perm('execute'):
97
+ <script>
98
+
99
+ ThisPageData.executeShowDialog = false
100
+ ThisPageData.executeSubmitting = false
101
+
102
+ ThisPage.methods.executeInit = function() {
103
+ this.executeShowDialog = true
104
+ }
105
+
106
+ ThisPage.methods.executeSubmit = function() {
107
+ this.executeSubmitting = true
108
+ this.$refs.executeForm.submit()
109
+ }
110
+
111
+ </script>
112
+ % endif
113
+ </%def>
@@ -16,6 +16,8 @@
16
16
  :default-sort="${grid.get_vue_first_sorter() or 'null'}"
17
17
  % endif
18
18
 
19
+ hoverable
20
+ narrowed
19
21
  icon-pack="fas">
20
22
 
21
23
  % for column in grid.get_vue_columns():
@@ -5,6 +5,17 @@
5
5
 
6
6
  <%def name="content_title()">${instance_title}</%def>
7
7
 
8
+ <%def name="extra_styles()">
9
+ ${parent.extra_styles()}
10
+ <style>
11
+
12
+ .wutta-form-wrapper {
13
+ width: 75%;
14
+ }
15
+
16
+ </style>
17
+ </%def>
18
+
8
19
  <%def name="render_instance_header_title_extras()">
9
20
  ${parent.render_instance_header_title_extras()}
10
21
  % if master.should_expose_versions():
@@ -21,7 +32,8 @@
21
32
 
22
33
  % if master.has_rows:
23
34
  <div style="display: flex; flex-direction: column;">
24
- <div style="display: flex; justify-content: space-between;">
35
+ <div class="block"
36
+ style="display: flex; justify-content: space-between;">
25
37
 
26
38
  ## main form
27
39
  <div style="flex-grow: 1;">
@@ -34,7 +46,6 @@
34
46
  </div>
35
47
 
36
48
  ## rows grid
37
- <br />
38
49
  <h4 class="block is-size-4">${master.get_rows_title() or ''}</h4>
39
50
  ${rows_grid.render_vue_tag()}
40
51
  </div>
@@ -5,6 +5,17 @@
5
5
 
6
6
  <%def name="content_title()">changes @ TXN ${transaction.id}</%def>
7
7
 
8
+ <%def name="extra_styles()">
9
+ ${parent.extra_styles()}
10
+ <style>
11
+
12
+ .wutta-form-wrapper {
13
+ width: 75%;
14
+ }
15
+
16
+ </style>
17
+ </%def>
18
+
8
19
  <%def name="page_content()">
9
20
  <div class="wutta-form-wrapper">
10
21
 
@@ -818,7 +818,7 @@
818
818
  } else if (dataType.type == 'UUID') {
819
819
  return `UUID()`
820
820
  } else if (dataType.type == '_fk_uuid_') {
821
- return 'sa.String(length=32)'
821
+ return `UUID()`
822
822
  } else if (dataType.type == '_other_') {
823
823
  return dataType.literal
824
824
  } else {
@@ -947,7 +947,7 @@
947
947
  } else {
948
948
  this.modelImportProblem = false
949
949
  this.modelImported = this.modelImportName
950
- this.revisionMessage = `add table for ${"$"}{this.tableModelTitlePlural}`
950
+ this.revisionMessage = `add ${"$"}{this.tableModelTitlePlural}`
951
951
  }
952
952
  }, 200)
953
953
  })
@@ -2,7 +2,7 @@
2
2
  ################################################################################
3
3
  #
4
4
  # wuttaweb -- Web App for Wutta Framework
5
- # Copyright © 2024-2025 Lance Edgar
5
+ # Copyright © 2024-2026 Lance Edgar
6
6
  #
7
7
  # This file is part of Wutta Framework.
8
8
  #
@@ -47,14 +47,15 @@ class AuthView(View):
47
47
  * route: ``login``
48
48
  * template: ``/auth/login.mako``
49
49
  """
50
+ # pylint: disable=duplicate-code
50
51
  model = self.app.model
51
52
  session = session or Session()
52
- auth = self.app.get_auth_handler()
53
53
 
54
54
  # nb. redirect to /setup if no users exist
55
55
  user = session.query(model.User).first()
56
56
  if not user:
57
57
  return self.redirect(self.request.route_url("setup"))
58
+ # pylint: enable=duplicate-code
58
59
 
59
60
  referrer = self.request.get_referrer()
60
61
 
@@ -79,8 +80,9 @@ class AuthView(View):
79
80
  if data:
80
81
 
81
82
  # truly validate user credentials
82
- user = auth.authenticate_user(session, data["username"], data["password"])
83
- if user:
83
+ if user := self.authenticate_user(
84
+ session, data["username"], data["password"]
85
+ ):
84
86
 
85
87
  # okay now they're truly logged in
86
88
  headers = login_user(self.request, user)
@@ -95,6 +97,12 @@ class AuthView(View):
95
97
  # 'referrer': referrer,
96
98
  }
97
99
 
100
+ def authenticate_user(
101
+ self, session, username, password
102
+ ): # pylint: disable=missing-function-docstring
103
+ auth = self.app.get_auth_handler()
104
+ return auth.authenticate_user(session, username, password)
105
+
98
106
  def login_make_schema(self): # pylint: disable=empty-docstring
99
107
  """ """
100
108
  schema = colander.Schema()
@@ -2,7 +2,7 @@
2
2
  ################################################################################
3
3
  #
4
4
  # wuttaweb -- Web App for Wutta Framework
5
- # Copyright © 2024-2025 Lance Edgar
5
+ # Copyright © 2024-2026 Lance Edgar
6
6
  #
7
7
  # This file is part of Wutta Framework.
8
8
  #
@@ -32,7 +32,7 @@ import markdown
32
32
  from sqlalchemy import orm
33
33
 
34
34
  from wuttaweb.views import MasterView
35
- from wuttaweb.forms.schema import UserRef
35
+ from wuttaweb.forms.schema import UserRef, WuttaDictEnum
36
36
  from wuttaweb.forms.widgets import BatchIdWidget
37
37
 
38
38
 
@@ -147,6 +147,9 @@ class BatchMasterView(MasterView):
147
147
  # description
148
148
  g.set_link("description")
149
149
 
150
+ # status_code
151
+ g.set_enum("status_code", self.model_class.STATUS)
152
+
150
153
  def render_batch_id( # pylint: disable=empty-docstring,unused-argument
151
154
  self, batch, key, value
152
155
  ):
@@ -191,6 +194,7 @@ class BatchMasterView(MasterView):
191
194
  if self.creating:
192
195
  f.remove("status_code")
193
196
  else:
197
+ f.set_node("status_code", WuttaDictEnum(self.request, batch.STATUS))
194
198
  f.set_readonly("status_code")
195
199
 
196
200
  # created
@@ -441,7 +445,7 @@ class BatchMasterView(MasterView):
441
445
  g.set_renderer("status_code", self.render_row_status)
442
446
 
443
447
  # tool button - create row
444
- if not batch.executed and self.has_perm("create_row"):
448
+ if self.rows_creatable and not batch.executed and self.has_perm("create_row"):
445
449
  button = self.make_button(
446
450
  f"New {self.get_row_model_title()}",
447
451
  primary=True,
@@ -2,7 +2,7 @@
2
2
  ################################################################################
3
3
  #
4
4
  # wuttaweb -- Web App for Wutta Framework
5
- # Copyright © 2024-2025 Lance Edgar
5
+ # Copyright © 2024-2026 Lance Edgar
6
6
  #
7
7
  # This file is part of Wutta Framework.
8
8
  #
@@ -51,6 +51,7 @@ class CommonView(View):
51
51
  This is normally the view shown when a user navigates to the
52
52
  root URL for the web app.
53
53
  """
54
+ # pylint: disable=duplicate-code
54
55
  model = self.app.model
55
56
  session = session or Session()
56
57
 
@@ -58,6 +59,7 @@ class CommonView(View):
58
59
  user = session.query(model.User).first()
59
60
  if not user:
60
61
  return self.redirect(self.request.route_url("setup"))
62
+ # pylint: enable=duplicate-code
61
63
 
62
64
  # maybe auto-redirect anons to login
63
65
  if not self.request.user:
@@ -201,19 +203,35 @@ class CommonView(View):
201
203
 
202
204
  # also make "Site Admin" role
203
205
  site_admin_perms = [
206
+ "alembic.migrations.list",
207
+ "alembic.migrations.create",
208
+ "alembic.migrations.view",
209
+ "alembic.migrations.delete",
210
+ "alembic.migrations.configure",
211
+ "alembic.dashboard",
212
+ "alembic.migrate",
213
+ "app_tables.list",
214
+ "app_tables.create",
215
+ "app_tables.view",
204
216
  "appinfo.list",
205
217
  "appinfo.configure",
218
+ "master_views.list",
219
+ "master_views.create",
220
+ "master_views.configure",
221
+ "app_tables.view",
206
222
  "people.list",
207
223
  "people.create",
208
224
  "people.view",
209
225
  "people.edit",
210
226
  "people.delete",
227
+ "people.versions",
211
228
  "roles.list",
212
229
  "roles.create",
213
230
  "roles.view",
214
231
  "roles.edit",
215
232
  "roles.edit_builtin",
216
233
  "roles.delete",
234
+ "roles.versions",
217
235
  "settings.list",
218
236
  "settings.create",
219
237
  "settings.view",
@@ -233,6 +251,7 @@ class CommonView(View):
233
251
  "users.view",
234
252
  "users.edit",
235
253
  "users.delete",
254
+ "users.versions",
236
255
  ]
237
256
  admin2 = model.Role(name="Site Admin")
238
257
  admin2.notes = (