WuttaWeb 0.26.0__tar.gz → 0.27.1__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.26.0 → wuttaweb-0.27.1}/CHANGELOG.md +34 -0
  2. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/PKG-INFO +3 -2
  3. wuttaweb-0.27.1/docs/api/wuttaweb.views.views.rst +6 -0
  4. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/index.rst +1 -0
  5. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/pyproject.toml +3 -3
  6. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/app.py +5 -0
  7. wuttaweb-0.27.1/src/wuttaweb/code-templates/new-master-view.mako +116 -0
  8. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/code-templates/new-table.mako +11 -15
  9. wuttaweb-0.27.1/src/wuttaweb/conf.py +89 -0
  10. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/db/continuum.py +8 -4
  11. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/forms/widgets.py +1 -1
  12. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/grids/base.py +28 -8
  13. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/alembic/dashboard.mako +4 -0
  14. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/appinfo/index.mako +30 -20
  15. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/base.mako +4 -0
  16. wuttaweb-0.27.1/src/wuttaweb/templates/batch/view.mako +113 -0
  17. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/form.mako +4 -0
  18. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/master/view.mako +2 -2
  19. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/tables/app/create.mako +2 -2
  20. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/tables/app/index.mako +8 -0
  21. wuttaweb-0.27.1/src/wuttaweb/templates/views/master/configure.mako +31 -0
  22. wuttaweb-0.27.1/src/wuttaweb/templates/views/master/create.mako +846 -0
  23. wuttaweb-0.27.1/src/wuttaweb/templates/views/master/index.mako +17 -0
  24. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/testing.py +55 -1
  25. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/views/batch.py +7 -3
  26. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/views/common.py +17 -0
  27. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/views/essential.py +2 -0
  28. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/views/master.py +30 -27
  29. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/views/people.py +3 -1
  30. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/views/reports.py +1 -0
  31. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/views/tables.py +95 -15
  32. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/views/upgrades.py +0 -6
  33. wuttaweb-0.27.1/src/wuttaweb/views/views.py +469 -0
  34. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tasks.py +2 -1
  35. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/db/test_continuum.py +8 -4
  36. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/forms/test_widgets.py +2 -1
  37. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/grids/test_base.py +19 -4
  38. wuttaweb-0.27.1/tests/test_conf.py +61 -0
  39. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/views/test_batch.py +1 -0
  40. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/views/test_tables.py +44 -1
  41. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/views/test_users.py +180 -1
  42. wuttaweb-0.27.1/tests/views/test_views.py +370 -0
  43. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tox.ini +8 -4
  44. wuttaweb-0.26.0/src/wuttaweb/conf.py +0 -46
  45. wuttaweb-0.26.0/src/wuttaweb/templates/batch/view.mako +0 -111
  46. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/.gitignore +0 -0
  47. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/.hgignore +0 -0
  48. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/.pylintrc +0 -0
  49. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/COPYING.txt +0 -0
  50. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/README.md +0 -0
  51. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/Makefile +0 -0
  52. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/_static/.keepme +0 -0
  53. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.app.rst +0 -0
  54. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.auth.rst +0 -0
  55. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.cli.rst +0 -0
  56. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.cli.webapp.rst +0 -0
  57. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.conf.rst +0 -0
  58. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.db.continuum.rst +0 -0
  59. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.db.rst +0 -0
  60. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.db.sess.rst +0 -0
  61. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.diffs.rst +0 -0
  62. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.emails.rst +0 -0
  63. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.forms.base.rst +0 -0
  64. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.forms.rst +0 -0
  65. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.forms.schema.rst +0 -0
  66. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.forms.widgets.rst +0 -0
  67. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.grids.base.rst +0 -0
  68. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.grids.filters.rst +0 -0
  69. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.grids.rst +0 -0
  70. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.handler.rst +0 -0
  71. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.helpers.rst +0 -0
  72. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.menus.rst +0 -0
  73. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.progress.rst +0 -0
  74. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.rst +0 -0
  75. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.static.rst +0 -0
  76. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.subscribers.rst +0 -0
  77. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.util.rst +0 -0
  78. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.views.alembic.rst +0 -0
  79. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.views.auth.rst +0 -0
  80. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.views.base.rst +0 -0
  81. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.views.batch.rst +0 -0
  82. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.views.common.rst +0 -0
  83. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.views.email.rst +0 -0
  84. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.views.essential.rst +0 -0
  85. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.views.master.rst +0 -0
  86. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.views.people.rst +0 -0
  87. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.views.progress.rst +0 -0
  88. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.views.reports.rst +0 -0
  89. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.views.roles.rst +0 -0
  90. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.views.rst +0 -0
  91. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.views.settings.rst +0 -0
  92. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.views.tables.rst +0 -0
  93. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.views.upgrades.rst +0 -0
  94. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/api/wuttaweb.views.users.rst +0 -0
  95. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/conf.py +0 -0
  96. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/glossary.rst +0 -0
  97. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/make.bat +0 -0
  98. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/narr/cli/builtin.rst +0 -0
  99. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/narr/cli/index.rst +0 -0
  100. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/narr/templates/base.rst +0 -0
  101. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/narr/templates/index.rst +0 -0
  102. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/narr/templates/lookup.rst +0 -0
  103. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/docs/narr/templates/overview.rst +0 -0
  104. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/__init__.py +0 -0
  105. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/_version.py +0 -0
  106. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/auth.py +0 -0
  107. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/cli/__init__.py +0 -0
  108. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/cli/webapp.py +0 -0
  109. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/db/__init__.py +0 -0
  110. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/db/sess.py +0 -0
  111. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/diffs.py +0 -0
  112. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/email-templates/feedback.html.mako +0 -0
  113. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/email-templates/feedback.txt.mako +0 -0
  114. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/emails.py +0 -0
  115. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/forms/__init__.py +0 -0
  116. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/forms/base.py +0 -0
  117. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/forms/schema.py +0 -0
  118. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/grids/__init__.py +0 -0
  119. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/grids/filters.py +0 -0
  120. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/handler.py +0 -0
  121. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/helpers.py +0 -0
  122. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/menus.py +0 -0
  123. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/progress.py +0 -0
  124. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/static/__init__.py +0 -0
  125. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/static/img/favicon.ico +0 -0
  126. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/static/img/logo.png +0 -0
  127. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/static/img/testing.png +0 -0
  128. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/subscribers.py +0 -0
  129. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/alembic/migrations/configure.mako +0 -0
  130. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/alembic/migrations/create.mako +0 -0
  131. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/alembic/migrations/index.mako +0 -0
  132. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/alembic/migrations/view.mako +0 -0
  133. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/appinfo/configure.mako +0 -0
  134. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/auth/change_password.mako +0 -0
  135. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/auth/login.mako +0 -0
  136. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/base_meta.mako +0 -0
  137. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/configure.mako +0 -0
  138. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/checkbox.pt +0 -0
  139. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/checkbox_choice.pt +0 -0
  140. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/checked_password.pt +0 -0
  141. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/dateinput.pt +0 -0
  142. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/datetimeinput.pt +0 -0
  143. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/moneyinput.pt +0 -0
  144. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/password.pt +0 -0
  145. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/permissions.pt +0 -0
  146. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/readonly/checkbox.pt +0 -0
  147. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/readonly/email_recips.pt +0 -0
  148. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/readonly/filedownload.pt +0 -0
  149. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/readonly/notes.pt +0 -0
  150. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/readonly/objectref.pt +0 -0
  151. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/readonly/permissions.pt +0 -0
  152. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/readonly/rolerefs.pt +0 -0
  153. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/select.pt +0 -0
  154. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/textarea.pt +0 -0
  155. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/textinput.pt +0 -0
  156. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/deform/wutta_checked_password.pt +0 -0
  157. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/diff.mako +0 -0
  158. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/email/settings/view.mako +0 -0
  159. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/forbidden.mako +0 -0
  160. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/forms/vue_buttons.mako +0 -0
  161. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/forms/vue_fields.mako +0 -0
  162. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/forms/vue_template.mako +0 -0
  163. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/grids/table_element.mako +0 -0
  164. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/grids/vue_template.mako +0 -0
  165. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/home.mako +0 -0
  166. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/master/configure.mako +0 -0
  167. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/master/create.mako +0 -0
  168. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/master/create_row.mako +0 -0
  169. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/master/delete.mako +0 -0
  170. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/master/edit.mako +0 -0
  171. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/master/form.mako +0 -0
  172. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/master/index.mako +0 -0
  173. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/master/view_version.mako +0 -0
  174. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/master/view_versions.mako +0 -0
  175. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/notfound.mako +0 -0
  176. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/page.mako +0 -0
  177. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/people/view_profile.mako +0 -0
  178. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/progress.mako +0 -0
  179. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/reports/view.mako +0 -0
  180. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/setup.mako +0 -0
  181. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/themes/butterfly/base.mako +0 -0
  182. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/themes/butterfly/buefy-components.mako +0 -0
  183. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/themes/butterfly/buefy-plugin.mako +0 -0
  184. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/themes/butterfly/http-plugin.mako +0 -0
  185. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/upgrade.mako +0 -0
  186. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/upgrades/configure.mako +0 -0
  187. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/upgrades/index.mako +0 -0
  188. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/upgrades/view.mako +0 -0
  189. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/users/view.mako +0 -0
  190. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/templates/wutta-components.mako +0 -0
  191. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/util.py +0 -0
  192. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/views/__init__.py +0 -0
  193. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/views/alembic.py +0 -0
  194. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/views/auth.py +0 -0
  195. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/views/base.py +0 -0
  196. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/views/email.py +0 -0
  197. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/views/progress.py +0 -0
  198. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/views/roles.py +0 -0
  199. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/views/settings.py +0 -0
  200. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/src/wuttaweb/views/users.py +0 -0
  201. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/__init__.py +0 -0
  202. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/cli/__init__.py +0 -0
  203. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/cli/test_webapp.py +0 -0
  204. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/db/__init__.py +0 -0
  205. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/forms/main_template.mako +0 -0
  206. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/forms/main_template_with_fields.mako +0 -0
  207. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/forms/test_base.py +0 -0
  208. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/forms/test_schema.py +0 -0
  209. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/grids/__init__.py +0 -0
  210. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/grids/test_filters.py +0 -0
  211. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/libcache/bb_fontawesome_svg_core.js +0 -0
  212. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/libcache/bb_free_solid_svg_icons.js +0 -0
  213. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/libcache/bb_oruga.js +0 -0
  214. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/libcache/bb_oruga_bulma.css +0 -0
  215. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/libcache/bb_oruga_bulma.js +0 -0
  216. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/libcache/bb_vue.js +0 -0
  217. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/libcache/bb_vue_fontawesome.js +0 -0
  218. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/libcache/buefy.css +0 -0
  219. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/libcache/buefy.js +0 -0
  220. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/libcache/fontawesome.js +0 -0
  221. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/libcache/vue.js +0 -0
  222. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/libcache/vue_resource.js +0 -0
  223. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/test_app.py +0 -0
  224. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/test_auth.py +0 -0
  225. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/test_diffs.py +0 -0
  226. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/test_emails.py +0 -0
  227. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/test_handler.py +0 -0
  228. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/test_helpers.py +0 -0
  229. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/test_menus.py +0 -0
  230. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/test_progress.py +0 -0
  231. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/test_static.py +0 -0
  232. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/test_subscribers.py +0 -0
  233. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/test_util.py +0 -0
  234. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/util.py +0 -0
  235. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/views/__init__.py +0 -0
  236. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/views/test___init__.py +0 -0
  237. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/views/test_alembic.py +0 -0
  238. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/views/test_auth.py +0 -0
  239. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/views/test_base.py +0 -0
  240. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/views/test_common.py +0 -0
  241. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/views/test_email.py +0 -0
  242. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/views/test_essential.py +0 -0
  243. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/views/test_master.py +0 -0
  244. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/views/test_people.py +0 -0
  245. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/views/test_progress.py +0 -0
  246. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/views/test_reports.py +0 -0
  247. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/views/test_roles.py +0 -0
  248. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/views/test_settings.py +0 -0
  249. {wuttaweb-0.26.0 → wuttaweb-0.27.1}/tests/views/test_upgrades.py +0 -0
@@ -5,6 +5,40 @@ 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.1 (2026-01-03)
9
+
10
+ ### Fix
11
+
12
+ - add separate def for middle buttons on App Info page
13
+ - expose version history for site admin in default setup
14
+ - only show execution panel if batch view supports it
15
+ - remove the Users field for create/edit Person
16
+ - only show "create row" button if batch view supports it
17
+ - show proper batch status text, from enum
18
+ - use wutta hint from model, for master view title
19
+ - accept dict instead of true enum, for `Grid.set_enum()`
20
+ - improve FK handling in generated model class code
21
+ - use custom UUID type when generating model class code for FK
22
+ - fix spacing style when viewing object with row grid
23
+ - grant access to alembic, tables, master view admin for new apps
24
+
25
+ ## v0.27.0 (2025-12-31)
26
+
27
+ ### Feat
28
+
29
+ - add wizard for generating new master view code
30
+ - add basic MasterView to show all registered master views
31
+ - add MasterView registry/discovery mechanism
32
+
33
+ ### Fix
34
+
35
+ - show db backend (dialect name) on App Info page
36
+ - prevent whitespace wrap for tool panel header
37
+ - render datetimes with tooltip showing time delta from now
38
+ - fallback to default continuum plugin logic, when no request
39
+ - flush session when creating new object via MasterView
40
+ - fix page title for Alembic Dashboard
41
+
8
42
  ## v0.26.0 (2025-12-28)
9
43
 
10
44
  ### Feat
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: WuttaWeb
3
- Version: 0.26.0
3
+ Version: 0.27.1
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
@@ -40,7 +40,7 @@ Requires-Dist: pyramid>=2
40
40
  Requires-Dist: sqlalchemy-utils
41
41
  Requires-Dist: waitress
42
42
  Requires-Dist: webhelpers2
43
- Requires-Dist: wuttjamaican[db]>=0.28.0
43
+ Requires-Dist: wuttjamaican[db]>=0.28.1
44
44
  Requires-Dist: zope-sqlalchemy>=1.5
45
45
  Provides-Extra: continuum
46
46
  Requires-Dist: wutta-continuum>=0.3.0; extra == 'continuum'
@@ -53,6 +53,7 @@ Requires-Dist: pylint; extra == 'tests'
53
53
  Requires-Dist: pytest; extra == 'tests'
54
54
  Requires-Dist: pytest-cov; extra == 'tests'
55
55
  Requires-Dist: tox; extra == 'tests'
56
+ Requires-Dist: webtest; extra == 'tests'
56
57
  Description-Content-Type: text/markdown
57
58
 
58
59
 
@@ -0,0 +1,6 @@
1
+
2
+ ``wuttaweb.views.views``
3
+ ========================
4
+
5
+ .. automodule:: wuttaweb.views.views
6
+ :members:
@@ -74,6 +74,7 @@ the narrative docs are pretty scant. That will eventually change.
74
74
  api/wuttaweb.views.tables
75
75
  api/wuttaweb.views.upgrades
76
76
  api/wuttaweb.views.users
77
+ api/wuttaweb.views.views
77
78
 
78
79
 
79
80
  Indices and tables
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
6
6
 
7
7
  [project]
8
8
  name = "WuttaWeb"
9
- version = "0.26.0"
9
+ version = "0.27.1"
10
10
  description = "Web App for Wutta Framework"
11
11
  readme = "README.md"
12
12
  authors = [{name = "Lance Edgar", email = "lance@wuttaproject.org"}]
@@ -45,7 +45,7 @@ dependencies = [
45
45
  "SQLAlchemy-Utils",
46
46
  "waitress",
47
47
  "WebHelpers2",
48
- "WuttJamaican[db]>=0.28.0",
48
+ "WuttJamaican[db]>=0.28.1",
49
49
  "zope.sqlalchemy>=1.5",
50
50
  ]
51
51
 
@@ -53,7 +53,7 @@ dependencies = [
53
53
  [project.optional-dependencies]
54
54
  continuum = ["Wutta-Continuum>=0.3.0"]
55
55
  docs = ["Sphinx", "furo", "sphinxcontrib-programoutput"]
56
- tests = ["pylint", "pytest", "pytest-cov", "tox"]
56
+ tests = ["pylint", "pytest", "pytest-cov", "tox", "WebTest"]
57
57
 
58
58
 
59
59
  [project.entry-points."fanstatic.libraries"]
@@ -164,6 +164,11 @@ def make_pyramid_config(settings):
164
164
  )
165
165
  pyramid_config.add_directive("add_wutta_permission", "wuttaweb.auth.add_permission")
166
166
 
167
+ # add some more config magic
168
+ pyramid_config.add_directive(
169
+ "add_wutta_master_view", "wuttaweb.conf.add_master_view"
170
+ )
171
+
167
172
  return pyramid_config
168
173
 
169
174
 
@@ -0,0 +1,116 @@
1
+ ## -*- coding: utf-8; mode: python; -*-
2
+ # -*- coding: utf-8; -*-
3
+ """
4
+ Master view for ${model_title_plural}
5
+ """
6
+
7
+ % if model_option == "model_class":
8
+ from ${model_module} import ${model_name}
9
+ % endif
10
+
11
+ from wuttaweb.views import MasterView
12
+
13
+
14
+ class ${class_name}(MasterView):
15
+ """
16
+ Master view for ${model_title_plural}
17
+ """
18
+ % if model_option == "model_class":
19
+ model_class = ${model_name}
20
+ % else:
21
+ model_name = "${model_name}"
22
+ % endif
23
+ model_title = "${model_title}"
24
+ model_title_plural = "${model_title_plural}"
25
+
26
+ route_prefix = "${route_prefix}"
27
+ % if permission_prefix != route_prefix:
28
+ permission_prefix = "${permission_prefix}"
29
+ % endif
30
+ url_prefix = "${url_prefix}"
31
+ % if template_prefix != url_prefix:
32
+ template_prefix = "${template_prefix}"
33
+ % endif
34
+
35
+ % if not listable:
36
+ listable = False
37
+ % endif
38
+ creatable = ${creatable}
39
+ % if not viewable:
40
+ viewable = ${viewable}
41
+ % endif
42
+ editable = ${editable}
43
+ deletable = ${deletable}
44
+
45
+ % if listable and model_option == "model_name":
46
+ filterable = False
47
+ sort_on_backend = False
48
+ paginate_on_backend = False
49
+ % endif
50
+
51
+ % if grid_columns:
52
+ grid_columns = [
53
+ % for field in grid_columns:
54
+ "${field}",
55
+ % endfor
56
+ ]
57
+ % elif model_option == "model_name":
58
+ # TODO: must specify grid columns before the list view will work:
59
+ # grid_columns = [
60
+ # "foo",
61
+ # "bar",
62
+ # ]
63
+ % endif
64
+
65
+ % if form_fields:
66
+ form_fields = [
67
+ % for field in form_fields:
68
+ "${field}",
69
+ % endfor
70
+ ]
71
+ % elif model_option == "model_name":
72
+ # TODO: must specify form fields before create/view/edit/delete will work:
73
+ # form_fields = [
74
+ # "foo",
75
+ # "bar",
76
+ # ]
77
+ % endif
78
+
79
+ % if listable and model_option == "model_name":
80
+ def get_grid_data(self, columns=None, session=None):
81
+ data = []
82
+
83
+ # TODO: you should return whatever data is needed for the grid.
84
+ # it is expected to be a list of dicts, with keys corresponding
85
+ # to grid columns.
86
+ #
87
+ # data = [
88
+ # {"foo": 1, "bar": "abc"},
89
+ # {"foo": 2, "bar": "def"},
90
+ # ]
91
+
92
+ return data
93
+ % endif
94
+
95
+ % if listable:
96
+ def configure_grid(self, grid):
97
+ g = grid
98
+ super().configure_grid(g)
99
+
100
+ # TODO: tweak grid however you need here
101
+ #
102
+ # g.set_label("foo", "FOO")
103
+ # g.set_link("foo")
104
+ # g.set_renderer("foo", self.render_special_field)
105
+ % endif
106
+
107
+
108
+ def defaults(config, **kwargs):
109
+ base = globals()
110
+
111
+ ${class_name} = kwargs.get('${class_name}', base['${class_name}'])
112
+ ${class_name}.defaults(config)
113
+
114
+
115
+ def includeme(config):
116
+ defaults(config)
@@ -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
 
@@ -0,0 +1,89 @@
1
+ # -*- coding: utf-8; -*-
2
+ ################################################################################
3
+ #
4
+ # wuttaweb -- Web App for Wutta Framework
5
+ # Copyright © 2024-2025 Lance Edgar
6
+ #
7
+ # This file is part of Wutta Framework.
8
+ #
9
+ # Wutta Framework is free software: you can redistribute it and/or modify it
10
+ # under the terms of the GNU General Public License as published by the Free
11
+ # Software Foundation, either version 3 of the License, or (at your option) any
12
+ # later version.
13
+ #
14
+ # Wutta Framework is distributed in the hope that it will be useful, but
15
+ # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17
+ # more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License along with
20
+ # Wutta Framework. If not, see <http://www.gnu.org/licenses/>.
21
+ #
22
+ ################################################################################
23
+ """
24
+ Config Extension
25
+ """
26
+
27
+ from wuttjamaican.conf import WuttaConfigExtension
28
+
29
+
30
+ class WuttaWebConfigExtension(WuttaConfigExtension):
31
+ """
32
+ Config extension for WuttaWeb.
33
+
34
+ This sets the default plugin used for SQLAlchemy-Continuum, to
35
+ :class:`~wuttaweb.db.continuum.WuttaWebContinuumPlugin`. Which is
36
+ only relevant if Wutta-Continuum is installed and enabled. For
37
+ more info see :doc:`wutta-continuum:index`.
38
+ """
39
+
40
+ key = "wuttaweb"
41
+
42
+ def configure(self, config): # pylint: disable=empty-docstring
43
+ """ """
44
+ config.setdefault(
45
+ "wutta_continuum.wutta_plugin_spec",
46
+ "wuttaweb.db.continuum:WuttaWebContinuumPlugin",
47
+ )
48
+
49
+
50
+ def add_master_view(config, master):
51
+ """
52
+ Pyramid directive to add the given ``MasterView`` subclass to the
53
+ app's registry.
54
+
55
+ This allows the app to dynamically present certain options for
56
+ admin features etc.
57
+
58
+ This is normally called automatically for all master views, within
59
+ the :meth:`~wuttaweb.views.master.MasterView.defaults()` method.
60
+
61
+ Should you need to call this yourself, do not call it directly but
62
+ instead make a similar call via the Pyramid config object::
63
+
64
+ pyramid_config.add_wutta_master_view(PoserWidgetView)
65
+
66
+ :param config: Reference to the Pyramid config object.
67
+
68
+ :param master: Reference to a
69
+ :class:`~wuttaweb.views.master.MasterView` subclass.
70
+
71
+ This function is involved in app startup; once that phase is
72
+ complete you can inspect the master views like so::
73
+
74
+ master_views = request.registry.settings["wuttaweb_master_views"]
75
+
76
+ # find master views for given model class
77
+ user_views = master_views.get(model.User, [])
78
+
79
+ # some master views are registered by model name instead (if no class)
80
+ email_views = master_views.get("email_setting", [])
81
+ """
82
+ key = master.get_model_class() or master.get_model_name()
83
+
84
+ def action():
85
+ master_views = config.get_settings().get("wuttaweb_master_views", {})
86
+ master_views.setdefault(key, []).append(master)
87
+ config.add_settings({"wuttaweb_master_views": master_views})
88
+
89
+ config.action(None, action)
@@ -48,11 +48,15 @@ else:
48
48
  request = get_current_request()
49
49
  if request:
50
50
  return request.client_addr
51
- return None
51
+
52
+ # nb. no request presumably means running as cli
53
+ return super().get_remote_addr(uow, session)
52
54
 
53
55
  def get_user_id(self, uow, session): # pylint: disable=empty-docstring
54
56
  """ """
55
57
  request = get_current_request()
56
- if request and request.user:
57
- return request.user.uuid
58
- return None
58
+ if request:
59
+ return request.user.uuid if request.user else None
60
+
61
+ # nb. no request presumably means running as cli
62
+ return super().get_user_id(uow, session)
@@ -274,7 +274,7 @@ class WuttaDateTimeWidget(DateTimeInputWidget):
274
274
  if not cstruct:
275
275
  return ""
276
276
  dt = datetime.datetime.fromisoformat(cstruct)
277
- return self.app.render_datetime(dt)
277
+ return self.app.render_datetime(dt, html=True)
278
278
 
279
279
  return super().serialize(field, cstruct, **kw)
280
280
 
@@ -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)
@@ -2041,7 +2047,7 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth
2041
2047
  grid.set_renderer('foo', 'datetime')
2042
2048
  """
2043
2049
  dt = getattr(obj, key)
2044
- return self.app.render_datetime(dt)
2050
+ return self.app.render_datetime(dt, html=True)
2045
2051
 
2046
2052
  def render_enum(self, obj, key, value, enum=None):
2047
2053
  """
@@ -2050,7 +2056,7 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth
2050
2056
  See also :meth:`set_enum()`.
2051
2057
 
2052
2058
  :param enum: Enum class for the field. This should be an
2053
- instance of :class:`~python:enum.Enum`.
2059
+ instance of :class:`~python:enum.Enum` or else a dict.
2054
2060
 
2055
2061
  To use this feature for your grid::
2056
2062
 
@@ -2061,12 +2067,26 @@ class Grid: # pylint: disable=too-many-instance-attributes,too-many-public-meth
2061
2067
  TWO = 2
2062
2068
  THREE = 3
2063
2069
 
2064
- grid.set_enum('my_enum_field', MyEnum)
2070
+ grid.set_enum("my_enum_field", MyEnum)
2071
+
2072
+ Or, perhaps more common::
2073
+
2074
+ myenum = {
2075
+ 1: "ONE",
2076
+ 2: "TWO",
2077
+ 3: "THREE",
2078
+ }
2079
+
2080
+ grid.set_enum("my_enum_field", myenum)
2065
2081
  """
2066
2082
  if enum:
2067
- raw_value = obj[key]
2068
- if raw_value:
2069
- return raw_value.value
2083
+
2084
+ if isinstance(enum, EnumType):
2085
+ if raw_value := obj[key]:
2086
+ return raw_value.value
2087
+
2088
+ if isinstance(enum, dict):
2089
+ return enum.get(value, value)
2070
2090
 
2071
2091
  return value
2072
2092
 
@@ -1,6 +1,10 @@
1
1
  ## -*- coding: utf-8; -*-
2
2
  <%inherit file="/page.mako" />
3
3
 
4
+ <%def name="title()">Alembic Dashboard</%def>
5
+
6
+ <%def name="content_title()"></%def>
7
+
4
8
  <%def name="page_content()">
5
9
  <div style="display: flex; gap: 5rem; align-items: start;">
6
10
 
@@ -19,6 +19,9 @@
19
19
  <b-field horizontal label="Node Title">
20
20
  <span>${app.get_node_title()}</span>
21
21
  </b-field>
22
+ <b-field horizontal label="DB Backend">
23
+ <span>${config.appdb_engine.dialect.name}</span>
24
+ </b-field>
22
25
  <b-field horizontal label="Time Zone">
23
26
  <span>${app.get_timezone_name()}</span>
24
27
  </b-field>
@@ -33,23 +36,7 @@
33
36
  </nav>
34
37
 
35
38
  <div class="buttons">
36
-
37
- % if request.has_perm("app_tables.list"):
38
- <wutta-button type="is-primary"
39
- tag="a" href="${url('app_tables')}"
40
- icon-left="table"
41
- label="App Tables"
42
- once />
43
- % endif
44
-
45
- % if request.has_perm("alembic.dashboard"):
46
- <wutta-button type="is-primary"
47
- tag="a" href="${url('alembic.dashboard')}"
48
- icon-left="forward"
49
- label="Alembic Dashboard"
50
- once />
51
- % endif
52
-
39
+ ${self.middle_buttons()}
53
40
  </div>
54
41
 
55
42
  <nav class="panel">
@@ -112,6 +99,32 @@
112
99
 
113
100
  </%def>
114
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
+
115
128
  <%def name="modify_vue_vars()">
116
129
  ${parent.modify_vue_vars()}
117
130
  <script>
@@ -124,6 +137,3 @@
124
137
 
125
138
  </script>
126
139
  </%def>
127
-
128
-
129
- ${parent.body()}
@@ -212,6 +212,10 @@
212
212
  padding: 1rem;
213
213
  }
214
214
 
215
+ .tool-panels-wrapper .panel-heading {
216
+ white-space: nowrap;
217
+ }
218
+
215
219
  </style>
216
220
  </%def>
217
221