WuttaWeb 0.22.0__tar.gz → 0.23.0__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.23.0/.hgignore +3 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/CHANGELOG.md +18 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/PKG-INFO +2 -2
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/pyproject.toml +2 -2
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/forms/widgets.py +16 -1
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/grids/base.py +32 -3
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/appinfo/configure.mako +10 -5
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/base.mako +7 -3
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/deform/checked_password.pt +2 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/deform/dateinput.pt +2 -1
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/deform/datetimeinput.pt +2 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/deform/moneyinput.pt +1 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/deform/password.pt +1 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/deform/textarea.pt +1 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/deform/textinput.pt +1 -0
- wuttaweb-0.23.0/src/wuttaweb/templates/deform/wutta_checked_password.pt +8 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/grids/table_element.mako +20 -1
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/themes/butterfly/buefy-components.mako +71 -29
- wuttaweb-0.23.0/src/wuttaweb/templates/users/view.mako +126 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/wutta-components.mako +49 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/util.py +7 -7
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/views/auth.py +7 -2
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/views/users.py +128 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/grids/test_base.py +44 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/test_util.py +14 -14
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/views/test_users.py +118 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/.gitignore +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/COPYING.txt +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/README.md +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/Makefile +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/_static/.keepme +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.app.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.auth.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.cli.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.cli.webapp.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.conf.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.db.continuum.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.db.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.db.sess.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.emails.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.forms.base.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.forms.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.forms.schema.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.forms.widgets.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.grids.base.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.grids.filters.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.grids.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.handler.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.helpers.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.menus.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.progress.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.static.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.subscribers.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.util.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.views.auth.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.views.base.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.views.batch.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.views.common.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.views.email.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.views.essential.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.views.master.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.views.people.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.views.progress.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.views.reports.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.views.roles.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.views.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.views.settings.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.views.upgrades.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/api/wuttaweb.views.users.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/conf.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/glossary.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/index.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/make.bat +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/narr/cli/builtin.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/narr/cli/index.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/narr/templates/base.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/narr/templates/index.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/narr/templates/lookup.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/docs/narr/templates/overview.rst +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/__init__.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/_version.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/app.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/auth.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/cli/__init__.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/cli/webapp.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/conf.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/db/__init__.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/db/continuum.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/db/sess.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/email-templates/feedback.html.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/email-templates/feedback.txt.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/emails.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/forms/__init__.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/forms/base.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/forms/schema.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/grids/__init__.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/grids/filters.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/handler.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/helpers.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/menus.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/progress.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/static/__init__.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/static/img/favicon.ico +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/static/img/logo.png +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/static/img/testing.png +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/subscribers.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/appinfo/index.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/auth/change_password.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/auth/login.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/base_meta.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/batch/view.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/configure.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/deform/checkbox.pt +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/deform/checkbox_choice.pt +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/deform/permissions.pt +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/deform/readonly/checkbox.pt +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/deform/readonly/email_recips.pt +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/deform/readonly/filedownload.pt +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/deform/readonly/notes.pt +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/deform/readonly/objectref.pt +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/deform/readonly/permissions.pt +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/deform/readonly/rolerefs.pt +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/deform/select.pt +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/email/settings/view.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/forbidden.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/form.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/forms/vue_template.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/grids/vue_template.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/home.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/master/configure.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/master/create.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/master/delete.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/master/edit.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/master/form.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/master/index.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/master/view.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/notfound.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/page.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/people/view_profile.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/progress.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/reports/view.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/setup.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/themes/butterfly/base.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/themes/butterfly/buefy-plugin.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/themes/butterfly/http-plugin.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/upgrade.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/upgrades/configure.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/upgrades/view.mako +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/testing.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/views/__init__.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/views/base.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/views/batch.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/views/common.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/views/email.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/views/essential.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/views/master.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/views/people.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/views/progress.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/views/reports.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/views/roles.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/views/settings.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/views/upgrades.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tasks.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/__init__.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/cli/__init__.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/cli/test_webapp.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/db/__init__.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/db/test_continuum.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/forms/test_base.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/forms/test_schema.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/forms/test_widgets.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/grids/__init__.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/grids/test_filters.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/libcache/bb_fontawesome_svg_core.js +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/libcache/bb_free_solid_svg_icons.js +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/libcache/bb_oruga.js +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/libcache/bb_oruga_bulma.css +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/libcache/bb_oruga_bulma.js +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/libcache/bb_vue.js +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/libcache/bb_vue_fontawesome.js +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/libcache/buefy.css +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/libcache/buefy.js +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/libcache/fontawesome.js +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/libcache/vue.js +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/libcache/vue_resource.js +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/test_app.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/test_auth.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/test_emails.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/test_handler.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/test_helpers.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/test_menus.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/test_progress.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/test_static.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/test_subscribers.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/util.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/views/__init__.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/views/test___init__.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/views/test_auth.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/views/test_base.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/views/test_batch.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/views/test_common.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/views/test_email.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/views/test_essential.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/views/test_master.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/views/test_people.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/views/test_progress.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/views/test_reports.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/views/test_roles.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/views/test_settings.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tests/views/test_upgrades.py +0 -0
- {wuttaweb-0.22.0 → wuttaweb-0.23.0}/tox.ini +0 -0
|
@@ -5,6 +5,24 @@ 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.23.0 (2025-08-09)
|
|
9
|
+
|
|
10
|
+
### Feat
|
|
11
|
+
|
|
12
|
+
- add tools to manage user API tokens
|
|
13
|
+
|
|
14
|
+
### Fix
|
|
15
|
+
|
|
16
|
+
- add default sorter, tools for basic table-element grid
|
|
17
|
+
- add custom password+confirmation widget for Vue3 + Oruga
|
|
18
|
+
- fix butterfly wrapper for b-notification component
|
|
19
|
+
- add butterfly wrapper for b-timepicker component
|
|
20
|
+
- style tweaks for butterfly/oruga; mostly expand fields
|
|
21
|
+
- fix b-datepicker component wrapper per oruga 0.9.0
|
|
22
|
+
- fix b-button component wrapper per oruga 0.9.0
|
|
23
|
+
- update butterfly component for b-autocomplete, per oruga 0.11.4
|
|
24
|
+
- update default versions for Vue3 + Oruga + FontAwesome
|
|
25
|
+
|
|
8
26
|
## v0.22.0 (2025-06-29)
|
|
9
27
|
|
|
10
28
|
### Feat
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: WuttaWeb
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.23.0
|
|
4
4
|
Summary: Web App for Wutta Framework
|
|
5
5
|
Project-URL: Homepage, https://wuttaproject.org/
|
|
6
6
|
Project-URL: Repository, https://forgejo.wuttaproject.org/wutta/wuttaweb
|
|
@@ -39,7 +39,7 @@ Requires-Dist: pyramid-tm
|
|
|
39
39
|
Requires-Dist: pyramid>=2
|
|
40
40
|
Requires-Dist: waitress
|
|
41
41
|
Requires-Dist: webhelpers2
|
|
42
|
-
Requires-Dist: wuttjamaican[db]>=0.
|
|
42
|
+
Requires-Dist: wuttjamaican[db]>=0.22.0
|
|
43
43
|
Requires-Dist: zope-sqlalchemy>=1.5
|
|
44
44
|
Provides-Extra: continuum
|
|
45
45
|
Requires-Dist: wutta-continuum; extra == 'continuum'
|
|
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "WuttaWeb"
|
|
9
|
-
version = "0.
|
|
9
|
+
version = "0.23.0"
|
|
10
10
|
description = "Web App for Wutta Framework"
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
authors = [{name = "Lance Edgar", email = "lance@wuttaproject.org"}]
|
|
@@ -44,7 +44,7 @@ dependencies = [
|
|
|
44
44
|
"pyramid_tm",
|
|
45
45
|
"waitress",
|
|
46
46
|
"WebHelpers2",
|
|
47
|
-
"WuttJamaican[db]>=0.
|
|
47
|
+
"WuttJamaican[db]>=0.22.0",
|
|
48
48
|
"zope.sqlalchemy>=1.5",
|
|
49
49
|
]
|
|
50
50
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
################################################################################
|
|
3
3
|
#
|
|
4
4
|
# wuttaweb -- Web App for Wutta Framework
|
|
5
|
-
# Copyright © 2024 Lance Edgar
|
|
5
|
+
# Copyright © 2024-2025 Lance Edgar
|
|
6
6
|
#
|
|
7
7
|
# This file is part of Wutta Framework.
|
|
8
8
|
#
|
|
@@ -153,6 +153,21 @@ class WuttaCheckboxChoiceWidget(CheckboxChoiceWidget):
|
|
|
153
153
|
self.app = self.config.get_app()
|
|
154
154
|
|
|
155
155
|
|
|
156
|
+
class WuttaCheckedPasswordWidget(PasswordWidget):
|
|
157
|
+
"""
|
|
158
|
+
Custom widget for password+confirmation field.
|
|
159
|
+
|
|
160
|
+
This widget is used only for Vue 3 + Oruga, but is *not* used for
|
|
161
|
+
Vue 2 + Buefy.
|
|
162
|
+
|
|
163
|
+
This is a subclass of :class:`deform:deform.widget.PasswordWidget`
|
|
164
|
+
and uses these Deform templates:
|
|
165
|
+
|
|
166
|
+
* ``wutta_checked_password``
|
|
167
|
+
"""
|
|
168
|
+
template = 'wutta_checked_password'
|
|
169
|
+
|
|
170
|
+
|
|
156
171
|
class WuttaDateWidget(DateInputWidget):
|
|
157
172
|
"""
|
|
158
173
|
Custom widget for :class:`python:datetime.date` fields.
|
|
@@ -2041,9 +2041,9 @@ class Grid:
|
|
|
2041
2041
|
"""
|
|
2042
2042
|
Render a simple Vue table element for the grid.
|
|
2043
2043
|
|
|
2044
|
-
This is what you want for a "simple" grid which does
|
|
2045
|
-
unique Vue component, but can instead use the
|
|
2046
|
-
component.
|
|
2044
|
+
This is what you want for a "simple" grid which does not
|
|
2045
|
+
require a unique Vue component, but can instead use the
|
|
2046
|
+
standard table component.
|
|
2047
2047
|
|
|
2048
2048
|
This returns something like:
|
|
2049
2049
|
|
|
@@ -2227,6 +2227,35 @@ class Grid:
|
|
|
2227
2227
|
'order': sorter['dir']})
|
|
2228
2228
|
return sorters
|
|
2229
2229
|
|
|
2230
|
+
def get_vue_first_sorter(self):
|
|
2231
|
+
"""
|
|
2232
|
+
Returns the first active sorter, if applicable.
|
|
2233
|
+
|
|
2234
|
+
This method is used to declare the initial sort for a simple
|
|
2235
|
+
table component, i.e. for use with the ``table-element.mako``
|
|
2236
|
+
template. It generally is assumed that frontend sorting is in
|
|
2237
|
+
use, as opposed to backend sorting, although it should work
|
|
2238
|
+
for either scenario.
|
|
2239
|
+
|
|
2240
|
+
This checks :attr:`active_sorters` and if set, will use the
|
|
2241
|
+
first sorter from that. Note that ``active_sorters`` will
|
|
2242
|
+
*not* be set unless :meth:`load_settings()` has been called.
|
|
2243
|
+
|
|
2244
|
+
Otherwise this will use the first sorter from
|
|
2245
|
+
:attr:`sort_defaults` which is defined in constructor.
|
|
2246
|
+
|
|
2247
|
+
:returns: The first sorter in format ``[sortkey, sortdir]``,
|
|
2248
|
+
or ``None``.
|
|
2249
|
+
"""
|
|
2250
|
+
if hasattr(self, 'active_sorters'):
|
|
2251
|
+
if self.active_sorters:
|
|
2252
|
+
sorter = self.active_sorters[0]
|
|
2253
|
+
return [sorter['key'], sorter['dir']]
|
|
2254
|
+
|
|
2255
|
+
elif self.sort_defaults:
|
|
2256
|
+
sorter = self.sort_defaults[0]
|
|
2257
|
+
return [sorter.sortkey, sorter.sortdir]
|
|
2258
|
+
|
|
2230
2259
|
def get_vue_filters(self):
|
|
2231
2260
|
"""
|
|
2232
2261
|
Returns a list of Vue-compatible filter definitions.
|
|
@@ -112,31 +112,36 @@
|
|
|
112
112
|
<b-field label="Default Sender">
|
|
113
113
|
<b-input name="${app.appname}.email.default.sender"
|
|
114
114
|
v-model="simpleSettings['${app.appname}.email.default.sender']"
|
|
115
|
-
@input="settingsNeedSaved = true"
|
|
115
|
+
@input="settingsNeedSaved = true"
|
|
116
|
+
expanded />
|
|
116
117
|
</b-field>
|
|
117
118
|
|
|
118
119
|
<b-field label="Default Recipient(s)">
|
|
119
120
|
<b-input name="${app.appname}.email.default.to"
|
|
120
121
|
v-model="simpleSettings['${app.appname}.email.default.to']"
|
|
121
|
-
@input="settingsNeedSaved = true"
|
|
122
|
+
@input="settingsNeedSaved = true"
|
|
123
|
+
expanded />
|
|
122
124
|
</b-field>
|
|
123
125
|
|
|
124
126
|
<b-field label="Default Subject (optional)">
|
|
125
127
|
<b-input name="${app.appname}.email.default.subject"
|
|
126
128
|
v-model="simpleSettings['${app.appname}.email.default.subject']"
|
|
127
|
-
@input="settingsNeedSaved = true"
|
|
129
|
+
@input="settingsNeedSaved = true"
|
|
130
|
+
expanded />
|
|
128
131
|
</b-field>
|
|
129
132
|
|
|
130
133
|
<b-field label="Feedback Recipient(s) (optional)">
|
|
131
134
|
<b-input name="${app.appname}.email.feedback.to"
|
|
132
135
|
v-model="simpleSettings['${app.appname}.email.feedback.to']"
|
|
133
|
-
@input="settingsNeedSaved = true"
|
|
136
|
+
@input="settingsNeedSaved = true"
|
|
137
|
+
expanded />
|
|
134
138
|
</b-field>
|
|
135
139
|
|
|
136
140
|
<b-field label="Feedback Subject (optional)">
|
|
137
141
|
<b-input name="${app.appname}.email.feedback.subject"
|
|
138
142
|
v-model="simpleSettings['${app.appname}.email.feedback.subject']"
|
|
139
|
-
@input="settingsNeedSaved = true"
|
|
143
|
+
@input="settingsNeedSaved = true"
|
|
144
|
+
expanded />
|
|
140
145
|
</b-field>
|
|
141
146
|
|
|
142
147
|
</div>
|
|
@@ -498,23 +498,26 @@
|
|
|
498
498
|
% if request.user:
|
|
499
499
|
disabled
|
|
500
500
|
% endif
|
|
501
|
-
/>
|
|
501
|
+
expanded />
|
|
502
502
|
</b-field>
|
|
503
503
|
|
|
504
504
|
<b-field label="Referring URL">
|
|
505
505
|
<b-input v-model="referrer"
|
|
506
|
-
disabled="true"
|
|
506
|
+
disabled="true"
|
|
507
|
+
expanded />
|
|
507
508
|
</b-field>
|
|
508
509
|
|
|
509
510
|
<b-field label="Message"
|
|
510
511
|
:type="message && message.trim() ? null : 'is-danger'">
|
|
511
512
|
<b-input type="textarea"
|
|
512
513
|
v-model="message"
|
|
513
|
-
ref="textarea"
|
|
514
|
+
ref="textarea"
|
|
515
|
+
expanded />
|
|
514
516
|
</b-field>
|
|
515
517
|
</section>
|
|
516
518
|
|
|
517
519
|
<footer class="modal-card-foot">
|
|
520
|
+
<div style="display: flex; gap: 0.5rem;">
|
|
518
521
|
<b-button @click="showDialog = false">
|
|
519
522
|
Cancel
|
|
520
523
|
</b-button>
|
|
@@ -525,6 +528,7 @@
|
|
|
525
528
|
:disabled="submitDisabled">
|
|
526
529
|
{{ sendingFeedback ? "Working, please wait..." : "Send Message" }}
|
|
527
530
|
</b-button>
|
|
531
|
+
</div>
|
|
528
532
|
</footer>
|
|
529
533
|
</div>
|
|
530
534
|
</${b}-modal>
|
|
@@ -5,10 +5,12 @@
|
|
|
5
5
|
<b-input name="${name}"
|
|
6
6
|
value="${field.widget.redisplay and cstruct or ''}"
|
|
7
7
|
type="password"
|
|
8
|
+
expanded
|
|
8
9
|
placeholder="Password" />
|
|
9
10
|
<b-input name="${name}-confirm"
|
|
10
11
|
value="${field.widget.redisplay and confirm or ''}"
|
|
11
12
|
type="password"
|
|
13
|
+
expanded
|
|
12
14
|
placeholder="Confirm Password" />
|
|
13
15
|
${field.end_mapping()}
|
|
14
16
|
</div>
|
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
## -*- coding: utf-8; -*-
|
|
2
|
-
|
|
2
|
+
<div>
|
|
3
|
+
|
|
4
|
+
% if grid.tools:
|
|
5
|
+
<div class="table-tools-wrapper">
|
|
6
|
+
% for html in grid.tools.values():
|
|
7
|
+
${html}
|
|
8
|
+
% endfor
|
|
9
|
+
</div>
|
|
10
|
+
% endif
|
|
11
|
+
|
|
12
|
+
<${b}-table :data="gridContext['${grid.key}'].data"
|
|
13
|
+
|
|
14
|
+
## sorting
|
|
15
|
+
% if grid.sortable:
|
|
16
|
+
:default-sort="${grid.get_vue_first_sorter() or 'null'}"
|
|
17
|
+
% endif
|
|
18
|
+
|
|
19
|
+
icon-pack="fas">
|
|
3
20
|
|
|
4
21
|
% for column in grid.get_vue_columns():
|
|
5
22
|
% if not column['hidden']:
|
|
@@ -52,3 +69,5 @@
|
|
|
52
69
|
</template>
|
|
53
70
|
|
|
54
71
|
</${b}-table>
|
|
72
|
+
|
|
73
|
+
</div>
|
{wuttaweb-0.22.0 → wuttaweb-0.23.0}/src/wuttaweb/templates/themes/butterfly/buefy-components.mako
RENAMED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
${self.make_b_checkbox_component()}
|
|
6
6
|
${self.make_b_collapse_component()}
|
|
7
7
|
${self.make_b_datepicker_component()}
|
|
8
|
+
${self.make_b_timepicker_component()}
|
|
8
9
|
${self.make_b_dropdown_component()}
|
|
9
10
|
${self.make_b_dropdown_item_component()}
|
|
10
11
|
${self.make_b_field_component()}
|
|
@@ -25,16 +26,10 @@
|
|
|
25
26
|
|
|
26
27
|
<%def name="make_b_autocomplete_component()">
|
|
27
28
|
<script type="text/x-template" id="b-autocomplete-template">
|
|
28
|
-
<o-autocomplete v-model="orugaValue"
|
|
29
|
-
:
|
|
30
|
-
|
|
31
|
-
:
|
|
32
|
-
:keep-first="keepFirst"
|
|
33
|
-
:clearable="clearable"
|
|
34
|
-
:clear-on-select="clearOnSelect"
|
|
35
|
-
:formatter="customFormatter"
|
|
36
|
-
:placeholder="placeholder"
|
|
37
|
-
@update:model-value="orugaValueUpdated"
|
|
29
|
+
<o-autocomplete v-model:input="orugaValue"
|
|
30
|
+
:options="options"
|
|
31
|
+
clear-icon="circle-xmark"
|
|
32
|
+
@update:input="orugaValueUpdated"
|
|
38
33
|
ref="autocomplete">
|
|
39
34
|
</o-autocomplete>
|
|
40
35
|
</script>
|
|
@@ -45,12 +40,7 @@
|
|
|
45
40
|
modelValue: String,
|
|
46
41
|
data: Array,
|
|
47
42
|
field: String,
|
|
48
|
-
openOnFocus: Boolean,
|
|
49
|
-
keepFirst: Boolean,
|
|
50
|
-
clearable: Boolean,
|
|
51
|
-
clearOnSelect: Boolean,
|
|
52
43
|
customFormatter: null,
|
|
53
|
-
placeholder: String,
|
|
54
44
|
},
|
|
55
45
|
data() {
|
|
56
46
|
return {
|
|
@@ -64,13 +54,33 @@
|
|
|
64
54
|
}
|
|
65
55
|
},
|
|
66
56
|
},
|
|
57
|
+
computed: {
|
|
58
|
+
options() {
|
|
59
|
+
const options = []
|
|
60
|
+
const field = this.field || 'label'
|
|
61
|
+
for (let opt of this.data) {
|
|
62
|
+
const newOpt = {
|
|
63
|
+
label: opt[field],
|
|
64
|
+
value: opt,
|
|
65
|
+
}
|
|
66
|
+
if (this.customFormatter) {
|
|
67
|
+
newOpt.label = this.customFormatter(opt)
|
|
68
|
+
}
|
|
69
|
+
options.push(newOpt)
|
|
70
|
+
}
|
|
71
|
+
return options
|
|
72
|
+
},
|
|
73
|
+
},
|
|
67
74
|
methods: {
|
|
68
75
|
focus() {
|
|
69
76
|
const input = this.$refs.autocomplete.$el.querySelector('input')
|
|
70
77
|
input.focus()
|
|
71
78
|
},
|
|
72
79
|
orugaValueUpdated(value) {
|
|
73
|
-
this
|
|
80
|
+
if (this.field) {
|
|
81
|
+
value = value[this.field]
|
|
82
|
+
}
|
|
83
|
+
this.$emit('update:modelValue', value || '')
|
|
74
84
|
},
|
|
75
85
|
},
|
|
76
86
|
}
|
|
@@ -82,7 +92,7 @@
|
|
|
82
92
|
<script type="text/x-template" id="b-button-template">
|
|
83
93
|
<o-button :variant="variant"
|
|
84
94
|
:size="orugaSize"
|
|
85
|
-
:
|
|
95
|
+
:type="nativeType"
|
|
86
96
|
:tag="tag"
|
|
87
97
|
:href="href"
|
|
88
98
|
:icon-left="iconLeft">
|
|
@@ -181,8 +191,8 @@
|
|
|
181
191
|
@update:model-value="orugaValueUpdated"
|
|
182
192
|
:value="value"
|
|
183
193
|
:placeholder="placeholder"
|
|
184
|
-
:
|
|
185
|
-
:
|
|
194
|
+
:formatter="dateFormatter"
|
|
195
|
+
:parser="dateParser"
|
|
186
196
|
:disabled="disabled"
|
|
187
197
|
:editable="editable"
|
|
188
198
|
:icon="icon"
|
|
@@ -228,6 +238,45 @@
|
|
|
228
238
|
<% request.register_component('b-datepicker', 'BDatepicker') %>
|
|
229
239
|
</%def>
|
|
230
240
|
|
|
241
|
+
<%def name="make_b_timepicker_component()">
|
|
242
|
+
<script type="text/x-template" id="b-timepicker-template">
|
|
243
|
+
<o-timepicker v-model="orugaValue"
|
|
244
|
+
@update:model-value="orugaValueUpdated"
|
|
245
|
+
:formatter="timeFormatter"
|
|
246
|
+
:parser="timeParser" />
|
|
247
|
+
</script>
|
|
248
|
+
<script>
|
|
249
|
+
const BTimepicker = {
|
|
250
|
+
template: '#b-timepicker-template',
|
|
251
|
+
props: {
|
|
252
|
+
modelValue: null,
|
|
253
|
+
timeFormatter: null,
|
|
254
|
+
timeParser: null,
|
|
255
|
+
},
|
|
256
|
+
data() {
|
|
257
|
+
return {
|
|
258
|
+
orugaValue: this.modelValue,
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
watch: {
|
|
262
|
+
modelValue(to, from) {
|
|
263
|
+
if (this.orugaValue != to) {
|
|
264
|
+
this.orugaValue = to
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
methods: {
|
|
269
|
+
orugaValueUpdate(value) {
|
|
270
|
+
if (this.modelValue != value) {
|
|
271
|
+
this.$emit('update:modelValue', value)
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
}
|
|
276
|
+
</script>
|
|
277
|
+
<% request.register_component('b-timepicker', 'BTimepicker') %>
|
|
278
|
+
</%def>
|
|
279
|
+
|
|
231
280
|
<%def name="make_b_dropdown_component()">
|
|
232
281
|
<script type="text/x-template" id="b-dropdown-template">
|
|
233
282
|
<o-dropdown :position="buefyPosition"
|
|
@@ -364,15 +413,7 @@
|
|
|
364
413
|
},
|
|
365
414
|
methods: {
|
|
366
415
|
focus() {
|
|
367
|
-
|
|
368
|
-
// TODO: this does not always work right?
|
|
369
|
-
this.$refs.input.$el.querySelector('textarea').focus()
|
|
370
|
-
} else {
|
|
371
|
-
// TODO: pretty sure we can rely on the <o-input> focus()
|
|
372
|
-
// here, but not sure why we weren't already doing that?
|
|
373
|
-
//this.$refs.input.$el.querySelector('input').focus()
|
|
374
|
-
this.$refs.input.focus()
|
|
375
|
-
}
|
|
416
|
+
this.$refs.input.focus()
|
|
376
417
|
},
|
|
377
418
|
},
|
|
378
419
|
}
|
|
@@ -445,7 +486,8 @@
|
|
|
445
486
|
<%def name="make_b_notification_component()">
|
|
446
487
|
<script type="text/x-template" id="b-notification-template">
|
|
447
488
|
<o-notification :variant="variant"
|
|
448
|
-
|
|
489
|
+
## nb. prop name changed for oruga
|
|
490
|
+
:closeable="closable">
|
|
449
491
|
<slot />
|
|
450
492
|
</o-notification>
|
|
451
493
|
</script>
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
## -*- coding: utf-8; -*-
|
|
2
|
+
<%inherit file="/master/view.mako" />
|
|
3
|
+
|
|
4
|
+
<%def name="page_content()">
|
|
5
|
+
${parent.page_content()}
|
|
6
|
+
|
|
7
|
+
% if master.has_perm('manage_api_tokens'):
|
|
8
|
+
<b-modal :active.sync="newTokenShowDialog"
|
|
9
|
+
has-modal-card>
|
|
10
|
+
<div class="modal-card">
|
|
11
|
+
<header class="modal-card-head">
|
|
12
|
+
<p class="modal-card-title">
|
|
13
|
+
New API Token
|
|
14
|
+
</p>
|
|
15
|
+
</header>
|
|
16
|
+
<section class="modal-card-body">
|
|
17
|
+
|
|
18
|
+
<div v-if="!newTokenSaved">
|
|
19
|
+
<b-field label="Description"
|
|
20
|
+
:type="{'is-danger': !newTokenDescription}">
|
|
21
|
+
<b-input v-model.trim="newTokenDescription"
|
|
22
|
+
expanded
|
|
23
|
+
ref="newTokenDescription">
|
|
24
|
+
</b-input>
|
|
25
|
+
</b-field>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<div v-if="newTokenSaved">
|
|
29
|
+
<p class="block">
|
|
30
|
+
Your new API token is shown below.
|
|
31
|
+
</p>
|
|
32
|
+
<p class="block">
|
|
33
|
+
IMPORTANT: You must record this token elsewhere
|
|
34
|
+
for later reference. You will NOT be able to
|
|
35
|
+
recover the value if you lose it.
|
|
36
|
+
</p>
|
|
37
|
+
<b-field horizontal label="API Token">
|
|
38
|
+
{{ newTokenRaw }}
|
|
39
|
+
</b-field>
|
|
40
|
+
<b-field horizontal label="Description">
|
|
41
|
+
{{ newTokenDescription }}
|
|
42
|
+
</b-field>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
</section>
|
|
46
|
+
<footer class="modal-card-foot">
|
|
47
|
+
<b-button @click="newTokenShowDialog = false">
|
|
48
|
+
{{ newTokenSaved ? "Close" : "Cancel" }}
|
|
49
|
+
</b-button>
|
|
50
|
+
<b-button v-if="!newTokenSaved"
|
|
51
|
+
type="is-primary"
|
|
52
|
+
icon-pack="fas"
|
|
53
|
+
icon-left="save"
|
|
54
|
+
@click="newTokenSave()"
|
|
55
|
+
:disabled="!newTokenDescription || newTokenSaving">
|
|
56
|
+
{{ newTokenSaving ? "Working, please wait..." : "Save" }}
|
|
57
|
+
</b-button>
|
|
58
|
+
</footer>
|
|
59
|
+
</div>
|
|
60
|
+
</b-modal>
|
|
61
|
+
% endif
|
|
62
|
+
</%def>
|
|
63
|
+
|
|
64
|
+
<%def name="render_form_tag()">
|
|
65
|
+
% if master.has_perm('manage_api_tokens'):
|
|
66
|
+
${form.render_vue_tag(**{'@new-token': 'newTokenInit', '@delete-token': 'deleteTokenInit'})}
|
|
67
|
+
% else:
|
|
68
|
+
${form.render_vue_tag()}
|
|
69
|
+
% endif
|
|
70
|
+
</%def>
|
|
71
|
+
|
|
72
|
+
<%def name="modify_vue_vars()">
|
|
73
|
+
${parent.modify_vue_vars()}
|
|
74
|
+
<script>
|
|
75
|
+
% if master.has_perm('manage_api_tokens'):
|
|
76
|
+
|
|
77
|
+
ThisPageData.newTokenShowDialog = false
|
|
78
|
+
ThisPageData.newTokenDescription = null
|
|
79
|
+
ThisPageData.newTokenRaw = null
|
|
80
|
+
ThisPageData.newTokenSaved = false
|
|
81
|
+
ThisPageData.newTokenSaving = false
|
|
82
|
+
|
|
83
|
+
ThisPage.methods.newTokenInit = function() {
|
|
84
|
+
this.newTokenDescription = null
|
|
85
|
+
this.newTokenRaw = null
|
|
86
|
+
this.newTokenSaved = false
|
|
87
|
+
this.newTokenShowDialog = true
|
|
88
|
+
this.$nextTick(() => {
|
|
89
|
+
this.$refs.newTokenDescription.focus()
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
ThisPage.methods.newTokenSave = function() {
|
|
94
|
+
this.newTokenSaving = true
|
|
95
|
+
|
|
96
|
+
const url = '${master.get_action_url('add_api_token', instance)}'
|
|
97
|
+
const params = {
|
|
98
|
+
description: this.newTokenDescription,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
this.wuttaPOST(url, params, response => {
|
|
102
|
+
this.newTokenSaving = false
|
|
103
|
+
this.newTokenRaw = response.data.token_string
|
|
104
|
+
${form.vue_component}Data.gridContext['users.view.api_tokens'].data.push(response.data)
|
|
105
|
+
this.newTokenSaved = true
|
|
106
|
+
}, response => {
|
|
107
|
+
this.newTokenSaving = false
|
|
108
|
+
})
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
ThisPage.methods.deleteTokenInit = function(token) {
|
|
112
|
+
if (!confirm("Really delete this API token?")) {
|
|
113
|
+
return
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const url = '${master.get_action_url('delete_api_token', instance)}'
|
|
117
|
+
const params = {uuid: token.uuid}
|
|
118
|
+
this.wuttaPOST(url, params, response => {
|
|
119
|
+
const i = ${form.vue_component}Data.gridContext['users.view.api_tokens'].data.indexOf(token)
|
|
120
|
+
${form.vue_component}Data.gridContext['users.view.api_tokens'].data.splice(i, 1)
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
% endif
|
|
125
|
+
</script>
|
|
126
|
+
</%def>
|