WuttaWeb 0.18.0__tar.gz → 0.19.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.
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/CHANGELOG.md +30 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/PKG-INFO +4 -3
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/README.md +1 -1
- wuttaweb-0.19.1/docs/api/wuttaweb.emails.rst +6 -0
- wuttaweb-0.19.1/docs/api/wuttaweb.views.email.rst +6 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/index.rst +2 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/pyproject.toml +3 -2
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/app.py +5 -2
- wuttaweb-0.19.1/src/wuttaweb/emails.py +48 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/forms/schema.py +91 -20
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/forms/widgets.py +112 -7
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/grids/base.py +112 -27
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/menus.py +6 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/progress.py +4 -1
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/base.mako +12 -8
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/batch/view.mako +1 -14
- wuttaweb-0.19.1/src/wuttaweb/templates/deform/readonly/email_recips.pt +5 -0
- wuttaweb-0.19.1/src/wuttaweb/templates/email/settings/view.mako +39 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/master/view.mako +15 -0
- wuttaweb-0.18.0/tests/util.py → wuttaweb-0.19.1/src/wuttaweb/testing.py +26 -39
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/util.py +33 -6
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/views/batch.py +11 -1
- wuttaweb-0.19.1/src/wuttaweb/views/email.py +298 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/views/essential.py +2 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/views/master.py +84 -1
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/db/test_continuum.py +1 -2
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/forms/test_schema.py +171 -93
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/forms/test_widgets.py +212 -94
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/grids/test_base.py +96 -1
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/grids/test_filters.py +1 -1
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/test_auth.py +1 -1
- wuttaweb-0.19.1/tests/test_emails.py +23 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/test_handler.py +1 -1
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/test_menus.py +1 -1
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/test_progress.py +5 -2
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/test_util.py +17 -6
- wuttaweb-0.19.1/tests/util.py +40 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/views/test___init__.py +1 -1
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/views/test_auth.py +1 -1
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/views/test_base.py +1 -1
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/views/test_batch.py +7 -1
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/views/test_common.py +1 -1
- wuttaweb-0.19.1/tests/views/test_email.py +211 -0
- wuttaweb-0.19.1/tests/views/test_essential.py +10 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/views/test_master.py +19 -1
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/views/test_people.py +1 -1
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/views/test_progress.py +1 -1
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/views/test_roles.py +1 -1
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/views/test_settings.py +1 -1
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/views/test_upgrades.py +1 -1
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/views/test_users.py +1 -1
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/.gitignore +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/COPYING.txt +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/Makefile +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/_static/.keepme +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.app.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.auth.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.cli.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.cli.webapp.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.conf.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.db.continuum.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.db.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.db.sess.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.forms.base.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.forms.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.forms.schema.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.forms.widgets.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.grids.base.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.grids.filters.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.grids.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.handler.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.helpers.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.menus.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.progress.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.static.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.subscribers.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.util.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.views.auth.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.views.base.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.views.batch.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.views.common.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.views.essential.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.views.master.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.views.people.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.views.progress.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.views.roles.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.views.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.views.settings.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.views.upgrades.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/api/wuttaweb.views.users.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/conf.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/glossary.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/make.bat +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/narr/cli/builtin.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/narr/cli/index.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/narr/templates/base.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/narr/templates/index.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/narr/templates/lookup.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/docs/narr/templates/overview.rst +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/__init__.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/_version.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/auth.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/cli/__init__.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/cli/webapp.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/conf.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/db/__init__.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/db/continuum.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/db/sess.py +0 -0
- {wuttaweb-0.18.0/src/wuttaweb/email/templates → wuttaweb-0.19.1/src/wuttaweb/email-templates}/feedback.html.mako +0 -0
- {wuttaweb-0.18.0/src/wuttaweb/email/templates → wuttaweb-0.19.1/src/wuttaweb/email-templates}/feedback.txt.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/forms/__init__.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/forms/base.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/grids/__init__.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/grids/filters.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/handler.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/helpers.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/static/__init__.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/static/img/favicon.ico +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/static/img/logo.png +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/static/img/testing.png +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/subscribers.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/appinfo/configure.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/appinfo/index.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/auth/change_password.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/auth/login.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/base_meta.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/configure.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/deform/checkbox.pt +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/deform/checkbox_choice.pt +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/deform/checked_password.pt +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/deform/dateinput.pt +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/deform/datetimeinput.pt +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/deform/moneyinput.pt +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/deform/password.pt +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/deform/permissions.pt +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/deform/readonly/checkbox.pt +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/deform/readonly/filedownload.pt +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/deform/readonly/notes.pt +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/deform/readonly/objectref.pt +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/deform/readonly/permissions.pt +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/deform/readonly/rolerefs.pt +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/deform/select.pt +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/deform/textarea.pt +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/deform/textinput.pt +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/forbidden.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/form.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/forms/vue_template.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/grids/table_element.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/grids/vue_template.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/home.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/master/configure.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/master/create.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/master/delete.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/master/edit.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/master/form.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/master/index.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/notfound.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/page.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/people/view_profile.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/progress.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/setup.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/upgrade.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/upgrades/configure.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/upgrades/view.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/templates/wutta-components.mako +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/views/__init__.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/views/auth.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/views/base.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/views/common.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/views/people.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/views/progress.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/views/roles.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/views/settings.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/views/upgrades.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/src/wuttaweb/views/users.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tasks.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/__init__.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/cli/__init__.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/cli/test_webapp.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/db/__init__.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/forms/__init__.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/forms/test_base.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/grids/__init__.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/libcache/bb_fontawesome_svg_core.js +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/libcache/bb_free_solid_svg_icons.js +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/libcache/bb_oruga.js +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/libcache/bb_oruga_bulma.css +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/libcache/bb_oruga_bulma.js +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/libcache/bb_vue.js +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/libcache/bb_vue_fontawesome.js +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/libcache/buefy.css +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/libcache/buefy.js +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/libcache/fontawesome.js +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/libcache/vue.js +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/libcache/vue_resource.js +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/test_app.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/test_helpers.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/test_static.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/test_subscribers.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/tests/views/__init__.py +0 -0
- {wuttaweb-0.18.0 → wuttaweb-0.19.1}/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.1 (2025-01-06)
|
|
9
|
+
|
|
10
|
+
### Fix
|
|
11
|
+
|
|
12
|
+
- improve built-in grid renderer logic
|
|
13
|
+
- allow session injection for ObjectRef constructor
|
|
14
|
+
- improve rendering for batch row status
|
|
15
|
+
- add basic support for row grid "view" action links
|
|
16
|
+
- add "xref buttons" tool panel for master view
|
|
17
|
+
- add WuttaQuantity schema type, widget
|
|
18
|
+
- remove `session` param from some form schema, widget classes
|
|
19
|
+
- add grid renderers for bool, currency, quantity
|
|
20
|
+
- use proper bulma styles for markdown content
|
|
21
|
+
- use span element for readonly money field widget render
|
|
22
|
+
- include grid filters for all column properties of model class
|
|
23
|
+
- use app handler to render error string, when progress fails
|
|
24
|
+
- add schema node type, widget for "money" (currency) fields
|
|
25
|
+
- exclude FK fields by default, for model forms
|
|
26
|
+
- fix style for header title text
|
|
27
|
+
|
|
28
|
+
## v0.19.0 (2024-12-23)
|
|
29
|
+
|
|
30
|
+
### Feat
|
|
31
|
+
|
|
32
|
+
- add feature to edit email settings, basic message preview
|
|
33
|
+
|
|
34
|
+
### Fix
|
|
35
|
+
|
|
36
|
+
- move CRUD header buttons toward center of screen
|
|
37
|
+
|
|
8
38
|
## v0.18.0 (2024-12-18)
|
|
9
39
|
|
|
10
40
|
### Feat
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: WuttaWeb
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.19.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
|
|
@@ -37,9 +37,10 @@ Requires-Dist: pyramid-fanstatic
|
|
|
37
37
|
Requires-Dist: pyramid-mako
|
|
38
38
|
Requires-Dist: pyramid-tm
|
|
39
39
|
Requires-Dist: pyramid>=2
|
|
40
|
+
Requires-Dist: sqlalchemy-utils
|
|
40
41
|
Requires-Dist: waitress
|
|
41
42
|
Requires-Dist: webhelpers2
|
|
42
|
-
Requires-Dist: wuttjamaican[db]>=0.
|
|
43
|
+
Requires-Dist: wuttjamaican[db]>=0.19.2
|
|
43
44
|
Requires-Dist: zope-sqlalchemy>=1.5
|
|
44
45
|
Provides-Extra: continuum
|
|
45
46
|
Requires-Dist: wutta-continuum; extra == 'continuum'
|
|
@@ -53,7 +54,7 @@ Requires-Dist: tox; extra == 'tests'
|
|
|
53
54
|
Description-Content-Type: text/markdown
|
|
54
55
|
|
|
55
56
|
|
|
56
|
-
#
|
|
57
|
+
# WuttaWeb
|
|
57
58
|
|
|
58
59
|
Web app for Wutta Framework
|
|
59
60
|
|
|
@@ -35,6 +35,7 @@ the narrative docs are pretty scant. That will eventually change.
|
|
|
35
35
|
api/wuttaweb.db
|
|
36
36
|
api/wuttaweb.db.continuum
|
|
37
37
|
api/wuttaweb.db.sess
|
|
38
|
+
api/wuttaweb.emails
|
|
38
39
|
api/wuttaweb.forms
|
|
39
40
|
api/wuttaweb.forms.base
|
|
40
41
|
api/wuttaweb.forms.schema
|
|
@@ -54,6 +55,7 @@ the narrative docs are pretty scant. That will eventually change.
|
|
|
54
55
|
api/wuttaweb.views.base
|
|
55
56
|
api/wuttaweb.views.batch
|
|
56
57
|
api/wuttaweb.views.common
|
|
58
|
+
api/wuttaweb.views.email
|
|
57
59
|
api/wuttaweb.views.essential
|
|
58
60
|
api/wuttaweb.views.master
|
|
59
61
|
api/wuttaweb.views.people
|
|
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "WuttaWeb"
|
|
9
|
-
version = "0.
|
|
9
|
+
version = "0.19.1"
|
|
10
10
|
description = "Web App for Wutta Framework"
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
authors = [{name = "Lance Edgar", email = "lance@wuttaproject.org"}]
|
|
@@ -42,9 +42,10 @@ dependencies = [
|
|
|
42
42
|
"pyramid_fanstatic",
|
|
43
43
|
"pyramid_mako",
|
|
44
44
|
"pyramid_tm",
|
|
45
|
+
"SQLAlchemy-Utils",
|
|
45
46
|
"waitress",
|
|
46
47
|
"WebHelpers2",
|
|
47
|
-
"WuttJamaican[db]>=0.
|
|
48
|
+
"WuttJamaican[db]>=0.19.2",
|
|
48
49
|
"zope.sqlalchemy>=1.5",
|
|
49
50
|
]
|
|
50
51
|
|
|
@@ -43,9 +43,12 @@ log = logging.getLogger(__name__)
|
|
|
43
43
|
class WebAppProvider(AppProvider):
|
|
44
44
|
"""
|
|
45
45
|
The :term:`app provider` for WuttaWeb. This adds some methods to
|
|
46
|
-
the :term:`app handler`, which are specific to web apps.
|
|
46
|
+
the :term:`app handler`, which are specific to web apps. It also
|
|
47
|
+
registers some :term:`email templates <email template>` for the
|
|
48
|
+
app, etc.
|
|
47
49
|
"""
|
|
48
|
-
|
|
50
|
+
email_modules = ['wuttaweb.emails']
|
|
51
|
+
email_templates = ['wuttaweb:email-templates']
|
|
49
52
|
|
|
50
53
|
def get_web_handler(self, **kwargs):
|
|
51
54
|
"""
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# -*- coding: utf-8; -*-
|
|
2
|
+
################################################################################
|
|
3
|
+
#
|
|
4
|
+
# wuttaweb -- Web App for Wutta Framework
|
|
5
|
+
# Copyright © 2024 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
|
+
:term:`Email Settings <email setting>` for WuttaWeb
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
from wuttjamaican.email import EmailSetting
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class feedback(EmailSetting):
|
|
31
|
+
"""
|
|
32
|
+
Sent when user submits feedback via the web app.
|
|
33
|
+
"""
|
|
34
|
+
default_subject = "User Feedback"
|
|
35
|
+
|
|
36
|
+
def sample_data(self):
|
|
37
|
+
""" """
|
|
38
|
+
model = self.app.model
|
|
39
|
+
person = model.Person(full_name="Barney Rubble")
|
|
40
|
+
user = model.User(username='barney', person=person)
|
|
41
|
+
return {
|
|
42
|
+
'user': user,
|
|
43
|
+
'user_name': str(person),
|
|
44
|
+
'user_url': '#',
|
|
45
|
+
'referrer': 'http://example.com/',
|
|
46
|
+
'client_ip': '127.0.0.1',
|
|
47
|
+
'message': "This app is cool but needs a new feature.\n\nAllow me to describe...",
|
|
48
|
+
}
|
|
@@ -30,9 +30,11 @@ import uuid as _uuid
|
|
|
30
30
|
import colander
|
|
31
31
|
import sqlalchemy as sa
|
|
32
32
|
|
|
33
|
+
from wuttjamaican.db.model import Person
|
|
34
|
+
from wuttjamaican.conf import parse_list
|
|
35
|
+
|
|
33
36
|
from wuttaweb.db import Session
|
|
34
37
|
from wuttaweb.forms import widgets
|
|
35
|
-
from wuttjamaican.db.model import Person
|
|
36
38
|
|
|
37
39
|
|
|
38
40
|
class WuttaDateTime(colander.DateTime):
|
|
@@ -153,25 +155,63 @@ class WuttaEnum(colander.Enum):
|
|
|
153
155
|
return widgets.SelectWidget(**kwargs)
|
|
154
156
|
|
|
155
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
|
+
|
|
169
|
+
def __init__(self, request, *args, **kwargs):
|
|
170
|
+
super().__init__(*args, **kwargs)
|
|
171
|
+
self.request = request
|
|
172
|
+
self.config = self.request.wutta_config
|
|
173
|
+
self.app = self.config.get_app()
|
|
174
|
+
|
|
175
|
+
def widget_maker(self, **kwargs):
|
|
176
|
+
""" """
|
|
177
|
+
return widgets.WuttaMoneyInputWidget(self.request, **kwargs)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class WuttaQuantity(colander.Decimal):
|
|
181
|
+
"""
|
|
182
|
+
Custom schema type for "quantity" fields.
|
|
183
|
+
|
|
184
|
+
This is a subclass of :class:`colander:colander.Decimal` but uses
|
|
185
|
+
:class:`~wuttaweb.forms.widgets.WuttaQuantityWidget` by default.
|
|
186
|
+
|
|
187
|
+
:param request: Current :term:`request` object.
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
def __init__(self, request, *args, **kwargs):
|
|
191
|
+
super().__init__(*args, **kwargs)
|
|
192
|
+
self.request = request
|
|
193
|
+
self.config = self.request.wutta_config
|
|
194
|
+
self.app = self.config.get_app()
|
|
195
|
+
|
|
196
|
+
def widget_maker(self, **kwargs):
|
|
197
|
+
""" """
|
|
198
|
+
return widgets.WuttaQuantityWidget(self.request, **kwargs)
|
|
199
|
+
|
|
200
|
+
|
|
156
201
|
class WuttaSet(colander.Set):
|
|
157
202
|
"""
|
|
158
203
|
Custom schema type for :class:`python:set` fields.
|
|
159
204
|
|
|
160
|
-
This is a subclass of :class:`colander.Set
|
|
161
|
-
Wutta-related params to the constructor.
|
|
205
|
+
This is a subclass of :class:`colander.Set`.
|
|
162
206
|
|
|
163
207
|
:param request: Current :term:`request` object.
|
|
164
|
-
|
|
165
|
-
:param session: Optional :term:`db session` to use instead of
|
|
166
|
-
:class:`wuttaweb.db.sess.Session`.
|
|
167
208
|
"""
|
|
168
209
|
|
|
169
|
-
def __init__(self, request
|
|
210
|
+
def __init__(self, request):
|
|
170
211
|
super().__init__()
|
|
171
212
|
self.request = request
|
|
172
213
|
self.config = self.request.wutta_config
|
|
173
214
|
self.app = self.config.get_app()
|
|
174
|
-
self.session = session or Session()
|
|
175
215
|
|
|
176
216
|
|
|
177
217
|
class ObjectRef(colander.SchemaType):
|
|
@@ -207,16 +247,16 @@ class ObjectRef(colander.SchemaType):
|
|
|
207
247
|
self,
|
|
208
248
|
request,
|
|
209
249
|
empty_option=None,
|
|
210
|
-
session=None,
|
|
211
250
|
*args,
|
|
212
251
|
**kwargs,
|
|
213
252
|
):
|
|
253
|
+
# nb. allow session injection for tests
|
|
254
|
+
self.session = kwargs.pop('session', Session())
|
|
214
255
|
super().__init__(*args, **kwargs)
|
|
215
256
|
self.request = request
|
|
216
257
|
self.config = self.request.wutta_config
|
|
217
258
|
self.app = self.config.get_app()
|
|
218
259
|
self.model_instance = None
|
|
219
|
-
self.session = session or Session()
|
|
220
260
|
|
|
221
261
|
if empty_option:
|
|
222
262
|
if empty_option is True:
|
|
@@ -448,7 +488,7 @@ class RoleRefs(WuttaSet):
|
|
|
448
488
|
:returns: Instance of
|
|
449
489
|
:class:`~wuttaweb.forms.widgets.RoleRefsWidget`.
|
|
450
490
|
"""
|
|
451
|
-
kwargs.setdefault('session',
|
|
491
|
+
session = kwargs.setdefault('session', Session())
|
|
452
492
|
|
|
453
493
|
if 'values' not in kwargs:
|
|
454
494
|
model = self.app.model
|
|
@@ -456,20 +496,20 @@ class RoleRefs(WuttaSet):
|
|
|
456
496
|
|
|
457
497
|
# avoid built-ins which cannot be assigned to users
|
|
458
498
|
avoid = {
|
|
459
|
-
auth.get_role_authenticated(
|
|
460
|
-
auth.get_role_anonymous(
|
|
499
|
+
auth.get_role_authenticated(session),
|
|
500
|
+
auth.get_role_anonymous(session),
|
|
461
501
|
}
|
|
462
502
|
avoid = set([role.uuid for role in avoid])
|
|
463
503
|
|
|
464
504
|
# also avoid admin unless current user is root
|
|
465
505
|
if not self.request.is_root:
|
|
466
|
-
avoid.add(auth.get_role_administrator(
|
|
506
|
+
avoid.add(auth.get_role_administrator(session).uuid)
|
|
467
507
|
|
|
468
508
|
# everything else can be (un)assigned for users
|
|
469
|
-
roles =
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
509
|
+
roles = session.query(model.Role)\
|
|
510
|
+
.filter(~model.Role.uuid.in_(avoid))\
|
|
511
|
+
.order_by(model.Role.name)\
|
|
512
|
+
.all()
|
|
473
513
|
values = [(role.uuid.hex, role.name) for role in roles]
|
|
474
514
|
kwargs['values'] = values
|
|
475
515
|
|
|
@@ -494,7 +534,7 @@ class UserRefs(WuttaSet):
|
|
|
494
534
|
:returns: Instance of
|
|
495
535
|
:class:`~wuttaweb.forms.widgets.UserRefsWidget`.
|
|
496
536
|
"""
|
|
497
|
-
kwargs.setdefault('session',
|
|
537
|
+
kwargs.setdefault('session', Session())
|
|
498
538
|
return widgets.UserRefsWidget(self.request, **kwargs)
|
|
499
539
|
|
|
500
540
|
|
|
@@ -524,7 +564,7 @@ class Permissions(WuttaSet):
|
|
|
524
564
|
:returns: Instance of
|
|
525
565
|
:class:`~wuttaweb.forms.widgets.PermissionsWidget`.
|
|
526
566
|
"""
|
|
527
|
-
kwargs.setdefault('session',
|
|
567
|
+
kwargs.setdefault('session', Session())
|
|
528
568
|
kwargs.setdefault('permissions', self.permissions)
|
|
529
569
|
|
|
530
570
|
if 'values' not in kwargs:
|
|
@@ -569,5 +609,36 @@ class FileDownload(colander.String):
|
|
|
569
609
|
return widgets.FileDownloadWidget(self.request, **kwargs)
|
|
570
610
|
|
|
571
611
|
|
|
612
|
+
class EmailRecipients(colander.String):
|
|
613
|
+
"""
|
|
614
|
+
Custom schema type for :term:`email setting` recipient fields
|
|
615
|
+
(``To``, ``Cc``, ``Bcc``).
|
|
616
|
+
"""
|
|
617
|
+
|
|
618
|
+
def serialize(self, node, appstruct):
|
|
619
|
+
if appstruct is colander.null:
|
|
620
|
+
return colander.null
|
|
621
|
+
|
|
622
|
+
return '\n'.join(parse_list(appstruct))
|
|
623
|
+
|
|
624
|
+
def deserialize(self, node, cstruct):
|
|
625
|
+
""" """
|
|
626
|
+
if cstruct is colander.null:
|
|
627
|
+
return colander.null
|
|
628
|
+
|
|
629
|
+
values = [value for value in parse_list(cstruct)
|
|
630
|
+
if value]
|
|
631
|
+
return ', '.join(values)
|
|
632
|
+
|
|
633
|
+
def widget_maker(self, **kwargs):
|
|
634
|
+
"""
|
|
635
|
+
Constructs a default widget for the field.
|
|
636
|
+
|
|
637
|
+
:returns: Instance of
|
|
638
|
+
:class:`~wuttaweb.forms.widgets.EmailRecipientsWidget`.
|
|
639
|
+
"""
|
|
640
|
+
return widgets.EmailRecipientsWidget(**kwargs)
|
|
641
|
+
|
|
642
|
+
|
|
572
643
|
# nb. colanderalchemy schema overrides
|
|
573
644
|
sa.DateTime.__colanderalchemy_config__ = {'typ': WuttaDateTime}
|
|
@@ -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
|
|
@@ -51,6 +52,8 @@ from deform.widget import (Widget, TextInputWidget, TextAreaWidget,
|
|
|
51
52
|
DateTimeInputWidget, MoneyInputWidget)
|
|
52
53
|
from webhelpers2.html import HTML
|
|
53
54
|
|
|
55
|
+
from wuttjamaican.conf import parse_list
|
|
56
|
+
|
|
54
57
|
from wuttaweb.db import Session
|
|
55
58
|
from wuttaweb.grids import Grid
|
|
56
59
|
|
|
@@ -133,26 +136,21 @@ class WuttaCheckboxChoiceWidget(CheckboxChoiceWidget):
|
|
|
133
136
|
Custom widget for :class:`python:set` fields.
|
|
134
137
|
|
|
135
138
|
This is a subclass of
|
|
136
|
-
:class:`deform:deform.widget.CheckboxChoiceWidget
|
|
137
|
-
Wutta-related params to the constructor.
|
|
139
|
+
:class:`deform:deform.widget.CheckboxChoiceWidget`.
|
|
138
140
|
|
|
139
141
|
:param request: Current :term:`request` object.
|
|
140
142
|
|
|
141
|
-
:param session: Optional :term:`db session` to use instead of
|
|
142
|
-
:class:`wuttaweb.db.sess.Session`.
|
|
143
|
-
|
|
144
143
|
It uses these Deform templates:
|
|
145
144
|
|
|
146
145
|
* ``checkbox_choice``
|
|
147
146
|
* ``readonly/checkbox_choice``
|
|
148
147
|
"""
|
|
149
148
|
|
|
150
|
-
def __init__(self, request,
|
|
149
|
+
def __init__(self, request, *args, **kwargs):
|
|
151
150
|
super().__init__(*args, **kwargs)
|
|
152
151
|
self.request = request
|
|
153
152
|
self.config = self.request.wutta_config
|
|
154
153
|
self.app = self.config.get_app()
|
|
155
|
-
self.session = session or Session()
|
|
156
154
|
|
|
157
155
|
|
|
158
156
|
class WuttaDateTimeWidget(DateTimeInputWidget):
|
|
@@ -192,6 +190,78 @@ class WuttaDateTimeWidget(DateTimeInputWidget):
|
|
|
192
190
|
return super().serialize(field, cstruct, **kw)
|
|
193
191
|
|
|
194
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
|
+
|
|
211
|
+
def __init__(self, request, *args, **kwargs):
|
|
212
|
+
super().__init__(*args, **kwargs)
|
|
213
|
+
self.request = request
|
|
214
|
+
self.config = self.request.wutta_config
|
|
215
|
+
self.app = self.config.get_app()
|
|
216
|
+
|
|
217
|
+
def serialize(self, field, cstruct, **kw):
|
|
218
|
+
""" """
|
|
219
|
+
readonly = kw.get('readonly', self.readonly)
|
|
220
|
+
if readonly:
|
|
221
|
+
if cstruct in (colander.null, None):
|
|
222
|
+
return HTML.tag('span')
|
|
223
|
+
cstruct = decimal.Decimal(cstruct)
|
|
224
|
+
return HTML.tag('span', c=[self.app.render_currency(cstruct)])
|
|
225
|
+
|
|
226
|
+
return super().serialize(field, cstruct, **kw)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class WuttaQuantityWidget(TextInputWidget):
|
|
230
|
+
"""
|
|
231
|
+
Custom widget for "quantity" fields. This is used by default for
|
|
232
|
+
:class:`~wuttaweb.forms.schema.WuttaQuantity` type nodes.
|
|
233
|
+
|
|
234
|
+
The main purpose of this widget is to leverage
|
|
235
|
+
:meth:`~wuttjamaican:wuttjamaican.app.AppHandler.render_quantity()`
|
|
236
|
+
for the readonly display.
|
|
237
|
+
|
|
238
|
+
This is a subclass of
|
|
239
|
+
:class:`deform:deform.widget.TextInputWidget` and uses these
|
|
240
|
+
Deform templates:
|
|
241
|
+
|
|
242
|
+
* ``textinput``
|
|
243
|
+
|
|
244
|
+
:param request: Current :term:`request` object.
|
|
245
|
+
"""
|
|
246
|
+
|
|
247
|
+
def __init__(self, request, *args, **kwargs):
|
|
248
|
+
super().__init__(*args, **kwargs)
|
|
249
|
+
self.request = request
|
|
250
|
+
self.config = self.request.wutta_config
|
|
251
|
+
self.app = self.config.get_app()
|
|
252
|
+
|
|
253
|
+
def serialize(self, field, cstruct, **kw):
|
|
254
|
+
""" """
|
|
255
|
+
readonly = kw.get('readonly', self.readonly)
|
|
256
|
+
if readonly:
|
|
257
|
+
if cstruct in (colander.null, None):
|
|
258
|
+
return HTML.tag('span')
|
|
259
|
+
cstruct = decimal.Decimal(cstruct)
|
|
260
|
+
return HTML.tag('span', c=[self.app.render_quantity(cstruct)])
|
|
261
|
+
|
|
262
|
+
return super().serialize(field, cstruct, **kw)
|
|
263
|
+
|
|
264
|
+
|
|
195
265
|
class FileDownloadWidget(Widget):
|
|
196
266
|
"""
|
|
197
267
|
Widget for use with :class:`~wuttaweb.forms.schema.FileDownload`
|
|
@@ -423,6 +493,41 @@ class PermissionsWidget(WuttaCheckboxChoiceWidget):
|
|
|
423
493
|
return super().serialize(field, cstruct, **kw)
|
|
424
494
|
|
|
425
495
|
|
|
496
|
+
class EmailRecipientsWidget(TextAreaWidget):
|
|
497
|
+
"""
|
|
498
|
+
Widget for :term:`email setting` recipient fields (``To``, ``Cc``,
|
|
499
|
+
``Bcc``).
|
|
500
|
+
|
|
501
|
+
This is a subclass of
|
|
502
|
+
:class:`deform:deform.widget.TextAreaWidget`. It uses these
|
|
503
|
+
Deform templates:
|
|
504
|
+
|
|
505
|
+
* ``textarea``
|
|
506
|
+
* ``readonly/email_recips``
|
|
507
|
+
|
|
508
|
+
See also the :class:`~wuttaweb.forms.schema.EmailRecipients`
|
|
509
|
+
schema type, which uses this widget.
|
|
510
|
+
"""
|
|
511
|
+
readonly_template = 'readonly/email_recips'
|
|
512
|
+
|
|
513
|
+
def serialize(self, field, cstruct, **kw):
|
|
514
|
+
""" """
|
|
515
|
+
readonly = kw.get('readonly', self.readonly)
|
|
516
|
+
if readonly:
|
|
517
|
+
kw['recips'] = parse_list(cstruct or '')
|
|
518
|
+
|
|
519
|
+
return super().serialize(field, cstruct, **kw)
|
|
520
|
+
|
|
521
|
+
def deserialize(self, field, pstruct):
|
|
522
|
+
""" """
|
|
523
|
+
if pstruct is colander.null:
|
|
524
|
+
return colander.null
|
|
525
|
+
|
|
526
|
+
values = [value for value in parse_list(pstruct)
|
|
527
|
+
if value]
|
|
528
|
+
return ', '.join(values)
|
|
529
|
+
|
|
530
|
+
|
|
426
531
|
class BatchIdWidget(Widget):
|
|
427
532
|
"""
|
|
428
533
|
Widget for use with the
|