accrete 0.0.142__tar.gz → 0.0.144__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.
- {accrete-0.0.142 → accrete-0.0.144}/.gitignore +2 -1
- {accrete-0.0.142 → accrete-0.0.144}/PKG-INFO +2 -2
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/log/admin.py +1 -1
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/system_mail/tasks.py +4 -5
- accrete-0.0.144/accrete/contrib/ui/__init__.py +19 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/filter.py +22 -13
- accrete-0.0.144/accrete/contrib/ui/response.py +540 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/css/accrete.css +69 -12
- accrete-0.0.144/accrete/contrib/ui/static/css/accrete.css.map +7 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/css/accrete.scss +370 -300
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/ui/content_right.html +2 -2
- accrete-0.0.144/accrete/contrib/ui/templates/ui/detail.html +11 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/ui/filter/filter.html +5 -5
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/ui/filter/query_tags.html +1 -1
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/ui/form_error.html +1 -1
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/ui/layout.html +69 -64
- accrete-0.0.144/accrete/contrib/ui/templates/ui/list.html +45 -0
- accrete-0.0.144/accrete/contrib/ui/templates/ui/list_update.html +9 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/ui/message.html +1 -1
- accrete-0.0.144/accrete/contrib/ui/templates/ui/modal.html +48 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/ui/table_row_update.html +2 -2
- accrete-0.0.144/accrete/contrib/ui/templates/ui/templatetags/field.html +19 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/ui/widgets/model_search_select.html +7 -7
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/ui/widgets/model_search_select_multi.html +3 -3
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templatetags/ui.py +24 -2
- accrete-0.0.144/accrete/contrib/user/templates/user/password_forgotten.html +1 -0
- accrete-0.0.144/accrete/contrib/user/templates/user/user_preferences.html +43 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/views.py +36 -37
- accrete-0.0.144/accrete/migrations/0008_alter_member_access_groups_and_more.py +23 -0
- accrete-0.0.144/accrete/migrations/__init__.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/utils/__init__.py +1 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/utils/forms.py +48 -28
- {accrete-0.0.142 → accrete-0.0.144}/accrete/utils/views.py +1 -2
- {accrete-0.0.142 → accrete-0.0.144}/accrete/views.py +2 -3
- {accrete-0.0.142 → accrete-0.0.144}/pyproject.toml +2 -2
- accrete-0.0.142/accrete/contrib/ui/__init__.py +0 -17
- accrete-0.0.142/accrete/contrib/ui/context.py +0 -123
- accrete-0.0.142/accrete/contrib/ui/static/css/.sass-cache/15adf1eed05371361b08787c918a7f18fc15be79/accrete.scssc +0 -0
- accrete-0.0.142/accrete/contrib/ui/static/css/accrete.css.map +0 -7
- accrete-0.0.142/accrete/contrib/ui/templates/ui/list.html +0 -43
- accrete-0.0.142/accrete/contrib/ui/templates/ui/list_update.html +0 -3
- accrete-0.0.142/accrete/contrib/ui/templates/ui/modal.html +0 -39
- accrete-0.0.142/accrete/contrib/ui/templates/ui/templatetags/field.html +0 -6
- accrete-0.0.142/accrete/contrib/ui/utils.py +0 -77
- accrete-0.0.142/accrete/contrib/user/templates/user/user_form.html +0 -58
- {accrete-0.0.142 → accrete-0.0.144}/LICENSE +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/README.md +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/__init__.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/admin.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/apps.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/config.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/context_processors.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/__init__.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/country/__init__.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/country/admin.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/country/apps.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/country/migrations/0001_initial.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/country/migrations/0002_auto_20250219_1759.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/country/migrations/0003_alter_country_options.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/country/migrations/__init__.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/country/models.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/log/__init__.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/log/apps.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/log/config.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/log/helper.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/log/migrations/0001_initial.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/log/migrations/0002_log_user_alter_log_new_value_type_and_more.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/log/migrations/0003_alter_log_tenant.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/log/migrations/0004_logconfig_logconfigfield.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/log/migrations/0005_logconfig_exclude_fields_and_more.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/log/migrations/__init__.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/log/models.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/log/queries.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/log/signals.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/log/tests.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/log/views.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/sequence/__init__.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/sequence/admin.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/sequence/apps.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/sequence/forms.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/sequence/migrations/0001_initial.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/sequence/migrations/0002_alter_sequence_name.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/sequence/migrations/0003_alter_sequence_tenant.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/sequence/migrations/__init__.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/sequence/models.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/sequence/queries.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/sequence/tests.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/sequence/views.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/system_mail/__init__.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/system_mail/admin.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/system_mail/apps.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/system_mail/forms.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/system_mail/migrations/0001_initial.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/system_mail/migrations/__init__.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/system_mail/models.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/system_mail/tests.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/system_mail/views.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/admin.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/apps.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/middleware.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/migrations/__init__.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/models.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/LICENSE +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/README.md +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/bulma.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/css/bulma.css +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/css/bulma.css.map +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/css/bulma.min.css +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/css/versions/bulma-no-dark-mode.css +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/css/versions/bulma-no-dark-mode.css.map +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/css/versions/bulma-no-dark-mode.min.css +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/css/versions/bulma-no-helpers-prefixed.css +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/css/versions/bulma-no-helpers-prefixed.css.map +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/css/versions/bulma-no-helpers-prefixed.min.css +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/css/versions/bulma-no-helpers.css +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/css/versions/bulma-no-helpers.css.map +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/css/versions/bulma-no-helpers.min.css +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/css/versions/bulma-prefixed.css +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/css/versions/bulma-prefixed.css.map +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/css/versions/bulma-prefixed.min.css +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/package.json +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/_index.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/base/_index.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/base/animations.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/base/generic.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/base/minireset.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/base/skeleton.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/components/_index.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/components/breadcrumb.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/components/card.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/components/dropdown.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/components/menu.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/components/message.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/components/modal.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/components/navbar.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/components/pagination.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/components/panel.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/components/tabs.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/elements/_index.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/elements/block.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/elements/box.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/elements/button.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/elements/content.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/elements/delete.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/elements/icon.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/elements/image.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/elements/loader.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/elements/notification.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/elements/progress.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/elements/table.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/elements/tag.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/elements/title.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/form/_index.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/form/checkbox-radio.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/form/file.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/form/input-textarea.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/form/select.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/form/shared.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/form/tools.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/grid/_index.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/grid/columns.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/grid/grid.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/helpers/_index.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/helpers/aspect-ratio.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/helpers/border.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/helpers/color.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/helpers/flexbox.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/helpers/float.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/helpers/gap.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/helpers/other.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/helpers/overflow.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/helpers/position.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/helpers/spacing.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/helpers/typography.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/helpers/visibility.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/layout/_index.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/layout/container.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/layout/footer.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/layout/hero.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/layout/level.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/layout/media.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/layout/section.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/themes/_index.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/themes/dark.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/themes/light.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/themes/setup.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/utilities/_index.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/utilities/controls.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/utilities/css-variables.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/utilities/derived-variables.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/utilities/extends.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/utilities/functions.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/utilities/initial-variables.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/sass/utilities/mixins.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/versions/bulma-no-dark-mode.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/versions/bulma-no-helpers-prefixed.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/versions/bulma-no-helpers.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/bulma/versions/bulma-prefixed.scss +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/css/fa.css +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/css/icons.css +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/icons/Logo.svg +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/icons/accrete.svg +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/js/alpine-3.14.9.js +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/js/alpine-focus-3.14.9.js +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/js/alpine-sort-3.14.9.js +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/js/filter.js +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/js/htmx.min.js +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/webfonts/fa-brands-400.ttf +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/webfonts/fa-brands-400.woff2 +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/webfonts/fa-regular-400.ttf +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/webfonts/fa-regular-400.woff2 +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/webfonts/fa-solid-900.ttf +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/webfonts/fa-solid-900.woff2 +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/webfonts/fa-v4compatibility.ttf +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/static/webfonts/fa-v4compatibility.woff2 +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/django/forms/widgets/attrs.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/django/forms/widgets/date.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/django/forms/widgets/email.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/django/forms/widgets/file.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/django/forms/widgets/input.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/django/forms/widgets/select.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/django/forms/widgets/text.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/django/forms/widgets/textarea.html +0 -0
- /accrete-0.0.142/accrete/contrib/ui/templatetags/__init__.py → /accrete-0.0.144/accrete/contrib/ui/templates/ui/content.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/ui/favicon.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/ui/filter/query_input.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/ui/filter/query_operator.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/ui/filter/query_params.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/ui/oob.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/ui/table.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/templates/ui/widgets/model_search_select_options.html +0 -0
- {accrete-0.0.142/accrete/contrib/user → accrete-0.0.144/accrete/contrib/ui/templatetags}/__init__.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/tests.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/urls.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/views.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/widgets/__init__.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/ui/widgets/search_select.py +0 -0
- {accrete-0.0.142/accrete/contrib/user/migrations → accrete-0.0.144/accrete/contrib/user}/__init__.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/admin.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/apps.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/auth_backends.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/forms.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/locale/de/LC_MESSAGES/django.mo +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/locale/de/LC_MESSAGES/django.po +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/middleware.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/migrations/0001_initial.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/migrations/0002_user_theme.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/migrations/0003_alter_user_email.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/migrations/0004_user_login_alter_user_email_user_email_or_login_set.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/migrations/0005_remove_user_email_or_login_set_and_more.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/migrations/0006_remove_user_email_or_login_set_user_is_managed_and_more.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/migrations/0007_user_managed_login.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/migrations/0008_remove_user_no_email_for_managed_user_and_more.py +0 -0
- {accrete-0.0.142/accrete/contrib/user_registration → accrete-0.0.144/accrete/contrib/user/migrations}/__init__.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/models.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/templates/user/accrete_navbar_end_dropdown.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/templates/user/change_email.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/templates/user/change_password.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/templates/user/login.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/tests.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user/urls.py +0 -0
- {accrete-0.0.142/accrete/contrib/user_registration/migrations → accrete-0.0.144/accrete/contrib/user_registration}/__init__.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user_registration/admin.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user_registration/apps.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user_registration/config.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user_registration/forms.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user_registration/migrations/0001_initial.py +0 -0
- {accrete-0.0.142/accrete → accrete-0.0.144/accrete/contrib/user_registration}/migrations/__init__.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user_registration/models.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user_registration/templates/user_registration/mail_templates/confirmation_mail.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user_registration/templates/user_registration/registration.html +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user_registration/tests.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user_registration/urls.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/contrib/user_registration/views.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/fields.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/forms.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/managers.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/middleware.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/migrations/0001_initial.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/migrations/0002_initial.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/migrations/0003_remove_member_name.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/migrations/0004_rename_accessgroupmember_memberaccessgrouprel_and_more.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/migrations/0005_accessgroup_apply_on_alter_member_access_groups_and_more.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/migrations/0006_alter_member_user.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/migrations/0007_accessgroup_description.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/models.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/storage.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/tenant.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/tests.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/urls.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/utils/dates.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/utils/log.py +0 -0
- {accrete-0.0.142 → accrete-0.0.144}/accrete/utils/models.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: accrete
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.144
|
4
4
|
Summary: Django Shared Schema Multi Tenant
|
5
5
|
Author-email: Benedikt Jilek <benedikt.jilek@pm.me>
|
6
6
|
License: Copyright (c) 2025 Benedikt Jilek
|
@@ -31,7 +31,7 @@ Classifier: Operating System :: OS Independent
|
|
31
31
|
Classifier: Programming Language :: Python :: 3
|
32
32
|
Classifier: Topic :: Internet :: WWW/HTTP
|
33
33
|
Requires-Python: >=3.10
|
34
|
-
Requires-Dist: django>=5.
|
34
|
+
Requires-Dist: django>=5.2
|
35
35
|
Provides-Extra: contrib
|
36
36
|
Requires-Dist: celery>=5.3.4; extra == 'contrib'
|
37
37
|
Requires-Dist: django-celery-beat; extra == 'contrib'
|
@@ -36,8 +36,7 @@ def run_mail_queue():
|
|
36
36
|
_logger.error(f'Failed to send system mail\n{error_str}')
|
37
37
|
email.error = error_str
|
38
38
|
email.save()
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
email.save()
|
39
|
+
else:
|
40
|
+
email.sent = True
|
41
|
+
email.error = None
|
42
|
+
email.save()
|
@@ -0,0 +1,19 @@
|
|
1
|
+
from . import widgets
|
2
|
+
from .filter import Filter
|
3
|
+
from .response import (
|
4
|
+
Response,
|
5
|
+
WindowResponse,
|
6
|
+
ListResponse,
|
7
|
+
ListEntryResponse,
|
8
|
+
TableResponse,
|
9
|
+
TableRowResponse,
|
10
|
+
DetailResponse,
|
11
|
+
ModalResponse,
|
12
|
+
OobResponse,
|
13
|
+
TriggerResponse,
|
14
|
+
ClientTrigger,
|
15
|
+
search_select_response,
|
16
|
+
message_response,
|
17
|
+
add_trigger,
|
18
|
+
update
|
19
|
+
)
|
@@ -46,12 +46,21 @@ class Filter:
|
|
46
46
|
TYPES_TIME = ['TimeField']
|
47
47
|
|
48
48
|
def __init__(
|
49
|
-
self,
|
49
|
+
self,
|
50
|
+
model,
|
51
|
+
query_dict: QueryDict,
|
52
|
+
default_lookup: str = None,
|
53
|
+
query: Q = None,
|
54
|
+
select_related: list[str] = None,
|
55
|
+
prefetch_related: list[str] = None
|
50
56
|
):
|
51
57
|
self.model = model
|
52
|
-
self.
|
58
|
+
self.query_dict = query_dict
|
53
59
|
self.model_name = f'{self.model._meta.app_label}.{self.model._meta.model_name}'
|
54
|
-
|
60
|
+
self.query = query or Q()
|
61
|
+
self.select_related = select_related
|
62
|
+
self.prefetch_related = prefetch_related
|
63
|
+
seen_models = query_dict.get('models', '').split(',')
|
55
64
|
self.seen_models = [
|
56
65
|
model for model in seen_models
|
57
66
|
if model and model != self.model_name
|
@@ -67,14 +76,14 @@ class Filter:
|
|
67
76
|
) -> paginator.Page:
|
68
77
|
return page_from_querystring(
|
69
78
|
self.model,
|
70
|
-
self.
|
71
|
-
select_related=select_related,
|
72
|
-
prefetch_related=prefetch_related,
|
73
|
-
query=query
|
79
|
+
self.query_dict,
|
80
|
+
select_related=select_related or self.select_related,
|
81
|
+
prefetch_related=prefetch_related or self.prefetch_related,
|
82
|
+
query=query or self.query
|
74
83
|
)
|
75
84
|
|
76
85
|
def get_queryset(self) -> QuerySet:
|
77
|
-
return filter_from_querystring(self.model, self.
|
86
|
+
return filter_from_querystring(self.model, self.query_dict)
|
78
87
|
|
79
88
|
def query_params(self):
|
80
89
|
fields = filter(
|
@@ -82,7 +91,7 @@ class Filter:
|
|
82
91
|
self.model._meta.get_fields()
|
83
92
|
)
|
84
93
|
params = []
|
85
|
-
path = self.
|
94
|
+
path = self.query_dict.get('path', '')
|
86
95
|
for field in fields:
|
87
96
|
field_params = self._get_field_params(field)
|
88
97
|
if not field.is_relation or field_params['model_name'] not in self.seen_models:
|
@@ -115,7 +124,7 @@ class Filter:
|
|
115
124
|
if not lookup:
|
116
125
|
ctx = {
|
117
126
|
'verbose_lookup': str(_('Select an attribute')),
|
118
|
-
'query_dict': self.
|
127
|
+
'query_dict': self.query_dict,
|
119
128
|
'model_name': self.model_name
|
120
129
|
}
|
121
130
|
return render_to_string('ui/filter/query_input.html', ctx)
|
@@ -133,14 +142,14 @@ class Filter:
|
|
133
142
|
'lookup': prefix + lookup,
|
134
143
|
'input': input_params,
|
135
144
|
'lookup_operator': lookup_operator,
|
136
|
-
'query_dict': self.
|
145
|
+
'query_dict': self.query_dict,
|
137
146
|
'model_name': self.model_name
|
138
147
|
}
|
139
148
|
return render_to_string('ui/filter/query_input.html', ctx)
|
140
149
|
|
141
150
|
def query_tags(self, query: list | dict = None, operator: str = None):
|
142
151
|
if not query:
|
143
|
-
query = json.loads(self.
|
152
|
+
query = json.loads(self.query_dict.get('q', '[]'))
|
144
153
|
if isinstance(query, dict):
|
145
154
|
query = [query]
|
146
155
|
operator = operator or '&'
|
@@ -291,7 +300,7 @@ class Filter:
|
|
291
300
|
return str(labels[lookup])
|
292
301
|
|
293
302
|
def _get_field_params(self, field):
|
294
|
-
path = self.
|
303
|
+
path = self.query_dict.get('path', '')
|
295
304
|
label = ''
|
296
305
|
name = field.name
|
297
306
|
if path:
|
@@ -0,0 +1,540 @@
|
|
1
|
+
import re
|
2
|
+
import ast
|
3
|
+
import json
|
4
|
+
from dataclasses import dataclass
|
5
|
+
|
6
|
+
from django.core import paginator
|
7
|
+
from django.db.models import Model
|
8
|
+
from django.http import HttpResponse
|
9
|
+
from django.template.loader import render_to_string
|
10
|
+
from django.utils.translation import gettext_lazy as _
|
11
|
+
from accrete.contrib.ui import Filter
|
12
|
+
|
13
|
+
|
14
|
+
class Response:
|
15
|
+
|
16
|
+
def __init__(self, *, template: str, context: dict):
|
17
|
+
self.template = template
|
18
|
+
self.context = context
|
19
|
+
|
20
|
+
@staticmethod
|
21
|
+
def add_trigger(response):
|
22
|
+
pass
|
23
|
+
|
24
|
+
def render(self, request) -> str:
|
25
|
+
return render_to_string(
|
26
|
+
template_name=self.template, context=self.context, request=request
|
27
|
+
)
|
28
|
+
|
29
|
+
def response(self, request, extra_content: str = None, replace_body: bool = False) -> HttpResponse:
|
30
|
+
extra_content = extra_content or ''
|
31
|
+
res = HttpResponse(content=(
|
32
|
+
self.render(request)
|
33
|
+
+ render_to_string('ui/message.html', request=request)
|
34
|
+
+ extra_content
|
35
|
+
))
|
36
|
+
self.add_trigger(res)
|
37
|
+
if replace_body:
|
38
|
+
res.headers['HX-Retarget'] = 'body'
|
39
|
+
res.headers['HX-Reswap'] = 'innerHTML'
|
40
|
+
res.headers['HX-Push-Url'] = request.path
|
41
|
+
return res
|
42
|
+
|
43
|
+
|
44
|
+
class OobResponse(Response):
|
45
|
+
|
46
|
+
oob_template = 'ui/oob.html'
|
47
|
+
|
48
|
+
def __init__(self, *, template: str, context: dict, swap: str, tag: str = 'div'):
|
49
|
+
super().__init__(template=self.oob_template, context=context)
|
50
|
+
self.context.update({'oob': {
|
51
|
+
'template': template,
|
52
|
+
'swap': swap,
|
53
|
+
'tag': tag
|
54
|
+
}})
|
55
|
+
|
56
|
+
|
57
|
+
class WindowResponse(Response):
|
58
|
+
|
59
|
+
base_template = 'ui/layout.html'
|
60
|
+
|
61
|
+
def __init__(
|
62
|
+
self, *,
|
63
|
+
title: str,
|
64
|
+
context: dict,
|
65
|
+
overview_template: str = None,
|
66
|
+
header_template: str = None,
|
67
|
+
panel_template: str = None,
|
68
|
+
is_centered: bool = False
|
69
|
+
):
|
70
|
+
super().__init__(template=self.base_template, context=context)
|
71
|
+
self.panel_template = panel_template
|
72
|
+
if 'has_panel' not in self.context.keys():
|
73
|
+
self.context.update(has_panel=self._has_panel())
|
74
|
+
self.context.update({
|
75
|
+
'title': title,
|
76
|
+
'overview_template': overview_template,
|
77
|
+
'header_template': header_template,
|
78
|
+
'panel_template': panel_template,
|
79
|
+
'is_centered': is_centered
|
80
|
+
})
|
81
|
+
|
82
|
+
def _has_panel(self):
|
83
|
+
return bool(self.panel_template)
|
84
|
+
|
85
|
+
def response(self, request, extra_content: str = None, replace_body: bool = True) -> HttpResponse:
|
86
|
+
return super().response(request, extra_content, replace_body)
|
87
|
+
|
88
|
+
|
89
|
+
class ListResponse(WindowResponse):
|
90
|
+
|
91
|
+
def __init__(
|
92
|
+
self, *,
|
93
|
+
title: str,
|
94
|
+
context: dict,
|
95
|
+
list_entry_template: str = None,
|
96
|
+
page: paginator.Page = None,
|
97
|
+
ui_filter: Filter = None,
|
98
|
+
endless_scroll: bool = True,
|
99
|
+
header_template: str = None,
|
100
|
+
panel_template: str = None,
|
101
|
+
column_count: int = 1,
|
102
|
+
column_height: str = '150px',
|
103
|
+
overview_template: str = 'ui/list.html'
|
104
|
+
):
|
105
|
+
assert page is not None or ui_filter is not None, _(
|
106
|
+
'Argument page or ui_filter must be supplied'
|
107
|
+
)
|
108
|
+
self.ui_filter = ui_filter
|
109
|
+
self.overview_template = overview_template
|
110
|
+
super().__init__(
|
111
|
+
title=title,
|
112
|
+
context=context,
|
113
|
+
overview_template=self.overview_template,
|
114
|
+
header_template=header_template,
|
115
|
+
panel_template=panel_template,
|
116
|
+
)
|
117
|
+
if ui_filter and not page:
|
118
|
+
page = ui_filter.get_page()
|
119
|
+
self.context.update({
|
120
|
+
'list_entry_template': list_entry_template,
|
121
|
+
'page': page,
|
122
|
+
'ui_filter': ui_filter,
|
123
|
+
'endless_scroll': endless_scroll,
|
124
|
+
'column_count': column_count,
|
125
|
+
'column_height': column_height
|
126
|
+
})
|
127
|
+
|
128
|
+
def _has_panel(self):
|
129
|
+
return bool(self.panel_template or self.ui_filter)
|
130
|
+
|
131
|
+
def response(self, request, extra_content: str = None, replace_body: bool = False) -> HttpResponse:
|
132
|
+
return super().response(request, extra_content, replace_body)
|
133
|
+
|
134
|
+
|
135
|
+
class ListEntryResponse(Response):
|
136
|
+
|
137
|
+
base_template = 'ui/list_update.html'
|
138
|
+
|
139
|
+
def __init__(
|
140
|
+
self, *,
|
141
|
+
instance: Model,
|
142
|
+
list_entry_template: str,
|
143
|
+
context: dict = None,
|
144
|
+
page: paginator.Page,
|
145
|
+
is_new: bool,
|
146
|
+
column_count: int = 1,
|
147
|
+
column_height: str = '150px',
|
148
|
+
):
|
149
|
+
self.page = page
|
150
|
+
super().__init__(template=self.base_template, context=context or {})
|
151
|
+
self.context.update({
|
152
|
+
'instance': instance,
|
153
|
+
'list_entry_template': list_entry_template,
|
154
|
+
'is_new': is_new,
|
155
|
+
'column_count': column_count,
|
156
|
+
'column_height': column_height
|
157
|
+
})
|
158
|
+
|
159
|
+
def render(self, request) -> str:
|
160
|
+
res = super().render(request)
|
161
|
+
if self.page:
|
162
|
+
pagination_update = OobResponse(
|
163
|
+
template='ui/layout.html#pagination',
|
164
|
+
swap='innerHTML:#pagination',
|
165
|
+
context=dict(page=self.page)
|
166
|
+
).render(request)
|
167
|
+
res += pagination_update
|
168
|
+
return res
|
169
|
+
|
170
|
+
|
171
|
+
class TableResponse(WindowResponse):
|
172
|
+
|
173
|
+
def __init__(
|
174
|
+
self, *,
|
175
|
+
title: str,
|
176
|
+
context: dict,
|
177
|
+
object_label: str,
|
178
|
+
fields: list[str],
|
179
|
+
footer: dict = None,
|
180
|
+
page: paginator.Page = None,
|
181
|
+
ui_filter: Filter = None,
|
182
|
+
endless_scroll: bool = True,
|
183
|
+
header_template: str = None,
|
184
|
+
panel_template: str = None,
|
185
|
+
overview_template: str = 'ui/table.html'
|
186
|
+
):
|
187
|
+
assert page is not None or ui_filter is not None, _(
|
188
|
+
'Argument page or ui_filter must be supplied'
|
189
|
+
)
|
190
|
+
self.ui_filter = ui_filter
|
191
|
+
self.overview_template = overview_template
|
192
|
+
super().__init__(
|
193
|
+
title=title,
|
194
|
+
context=context,
|
195
|
+
overview_template=self.overview_template,
|
196
|
+
header_template=header_template,
|
197
|
+
panel_template=panel_template
|
198
|
+
)
|
199
|
+
if ui_filter and not page:
|
200
|
+
page = ui_filter.get_page()
|
201
|
+
self.context.update({
|
202
|
+
'page': page,
|
203
|
+
'ui_filter': ui_filter,
|
204
|
+
'endless_scroll': endless_scroll,
|
205
|
+
'fields': fields,
|
206
|
+
'object_label': object_label,
|
207
|
+
'footer': footer
|
208
|
+
})
|
209
|
+
|
210
|
+
def _has_panel(self):
|
211
|
+
return bool(self.panel_template or self.ui_filter)
|
212
|
+
|
213
|
+
def response(self, request, extra_content: str = None, replace_body: bool = False) -> HttpResponse:
|
214
|
+
return super().response(request, extra_content, replace_body)
|
215
|
+
|
216
|
+
|
217
|
+
class TableRowResponse(Response):
|
218
|
+
|
219
|
+
base_template = 'ui/table_row_update.html'
|
220
|
+
|
221
|
+
def __init__(
|
222
|
+
self, *,
|
223
|
+
instance: Model,
|
224
|
+
fields: list[str],
|
225
|
+
footer: dict = None,
|
226
|
+
page: paginator.Page = None,
|
227
|
+
):
|
228
|
+
self.page = page
|
229
|
+
context = {
|
230
|
+
'instance': instance,
|
231
|
+
'fields': fields,
|
232
|
+
'footer': footer,
|
233
|
+
}
|
234
|
+
super().__init__(template=self.base_template, context=context)
|
235
|
+
|
236
|
+
def render(self, request) -> str:
|
237
|
+
res = super().render(request)
|
238
|
+
if self.page:
|
239
|
+
pagination_update = OobResponse(
|
240
|
+
template='ui/layout.html#pagination',
|
241
|
+
swap='innerHTML:#pagination',
|
242
|
+
context=dict(page=self.page)
|
243
|
+
).render(request)
|
244
|
+
res += pagination_update
|
245
|
+
return res
|
246
|
+
|
247
|
+
|
248
|
+
class DetailResponse(Response):
|
249
|
+
|
250
|
+
base_template = 'ui/detail.html'
|
251
|
+
|
252
|
+
def __init__(
|
253
|
+
self, *,
|
254
|
+
context: dict,
|
255
|
+
detail_header_template: str = None,
|
256
|
+
detail_data_template: str = None
|
257
|
+
):
|
258
|
+
super().__init__(template=self.base_template, context=context)
|
259
|
+
self.context.update({
|
260
|
+
'detail_header_template': detail_header_template,
|
261
|
+
'detail_data_template': detail_data_template
|
262
|
+
})
|
263
|
+
|
264
|
+
@staticmethod
|
265
|
+
def add_trigger(response):
|
266
|
+
add_trigger(response, 'activate-detail')
|
267
|
+
|
268
|
+
|
269
|
+
class ModalResponse(Response):
|
270
|
+
|
271
|
+
def __init__(
|
272
|
+
self, *,
|
273
|
+
modal_id: str,
|
274
|
+
template: str,
|
275
|
+
context: dict,
|
276
|
+
title: str = None,
|
277
|
+
is_update: bool = False,
|
278
|
+
is_blocking: bool = False,
|
279
|
+
modal_width: str = None
|
280
|
+
|
281
|
+
):
|
282
|
+
super().__init__(template=template, context=context)
|
283
|
+
self.context.update({
|
284
|
+
'title': title,
|
285
|
+
'modal_id': re.sub(r'[^A-Za-z-]+', '', modal_id).strip('-'),
|
286
|
+
'is_update': is_update,
|
287
|
+
'is_blocking': is_blocking,
|
288
|
+
'modal_width': modal_width
|
289
|
+
})
|
290
|
+
|
291
|
+
|
292
|
+
@dataclass
|
293
|
+
class ClientTrigger:
|
294
|
+
|
295
|
+
trigger: dict | str
|
296
|
+
header: str = 'HX-Trigger'
|
297
|
+
|
298
|
+
|
299
|
+
class TriggerResponse:
|
300
|
+
|
301
|
+
def __init__(self, trigger: list[ClientTrigger]):
|
302
|
+
self.trigger = trigger
|
303
|
+
|
304
|
+
def response(self):
|
305
|
+
res = HttpResponse()
|
306
|
+
res.headers['HX-Reswap'] = 'None'
|
307
|
+
for trigger in self.trigger:
|
308
|
+
add_trigger(res, trigger.trigger, trigger.header)
|
309
|
+
return res
|
310
|
+
|
311
|
+
|
312
|
+
# @dataclass(kw_only=True)
|
313
|
+
# class Response:
|
314
|
+
#
|
315
|
+
# template: str
|
316
|
+
# context: dict = field(default_factory=dict)
|
317
|
+
#
|
318
|
+
# base_template = None
|
319
|
+
#
|
320
|
+
# def __post_init__(self):
|
321
|
+
# for key, value in self.context.items():
|
322
|
+
# setattr(self, key, value)
|
323
|
+
# if self.base_template is None:
|
324
|
+
# self.base_template = self.template
|
325
|
+
#
|
326
|
+
# def dict(self):
|
327
|
+
# return {
|
328
|
+
# attr: getattr(self, attr, None) for attr
|
329
|
+
# in filter(lambda x: not x.startswith('_'), self.__dict__)
|
330
|
+
# }
|
331
|
+
#
|
332
|
+
# @staticmethod
|
333
|
+
# def add_trigger(response):
|
334
|
+
# pass
|
335
|
+
#
|
336
|
+
# def render(self, request) -> str:
|
337
|
+
# return render_to_string(
|
338
|
+
# template_name=self.base_template, context=self.dict(), request=request
|
339
|
+
# )
|
340
|
+
#
|
341
|
+
# def response(self, request, extra_content: str = None) -> HttpResponse:
|
342
|
+
# extra_content = extra_content or ''
|
343
|
+
# res = HttpResponse(content=(
|
344
|
+
# self.render(request)
|
345
|
+
# + render_to_string('ui/message.html', self.dict(), request)
|
346
|
+
# + extra_content
|
347
|
+
# ))
|
348
|
+
# self.add_trigger(res)
|
349
|
+
# return res
|
350
|
+
#
|
351
|
+
#
|
352
|
+
# @dataclass(kw_only=True)
|
353
|
+
# class OobResponse(Response):
|
354
|
+
#
|
355
|
+
# swap: str
|
356
|
+
# tag: str = 'div'
|
357
|
+
# id: str = None
|
358
|
+
#
|
359
|
+
# base_template = 'ui/oob.html'
|
360
|
+
#
|
361
|
+
# def dict(self) -> dict:
|
362
|
+
# attributes = filter(
|
363
|
+
# lambda x: not x.startswith('_') and x not in ['template', 'swap', 'tag'],
|
364
|
+
# self.__dict__
|
365
|
+
# )
|
366
|
+
# res = {attr: getattr(self, attr, None) for attr in attributes}
|
367
|
+
# res.update({'oob': {
|
368
|
+
# 'template': self.template,
|
369
|
+
# 'id': self.id,
|
370
|
+
# 'swap': self.swap,
|
371
|
+
# 'tag': self.tag
|
372
|
+
# }})
|
373
|
+
# return res
|
374
|
+
#
|
375
|
+
# # def render(self, request) -> str:
|
376
|
+
# # return render_to_string(
|
377
|
+
# # template_name='ui/oob.html', context=self.dict(), request=request
|
378
|
+
# # )
|
379
|
+
#
|
380
|
+
#
|
381
|
+
# @dataclass(kw_only=True)
|
382
|
+
# class WindowResponse(Response):
|
383
|
+
#
|
384
|
+
# title: str = ''
|
385
|
+
# panel_template: str = None
|
386
|
+
# overview_header_template: str = None
|
387
|
+
# overview_data_template: str = None
|
388
|
+
#
|
389
|
+
# base_template = 'ui/layout.html'
|
390
|
+
#
|
391
|
+
# def __post_init__(self):
|
392
|
+
# if 'has_panel' not in self.context.keys():
|
393
|
+
# self.context.update(has_panel=self._has_panel())
|
394
|
+
# super().__post_init__()
|
395
|
+
# if self.template:
|
396
|
+
# self.base_template = self.template
|
397
|
+
#
|
398
|
+
# def _has_panel(self) -> bool:
|
399
|
+
# return bool(self.panel_template)
|
400
|
+
#
|
401
|
+
#
|
402
|
+
# @dataclass(kw_only=True)
|
403
|
+
# class PageResponse(WindowResponse):
|
404
|
+
#
|
405
|
+
# page: paginator.Page = None
|
406
|
+
# ui_filter: Filter = None
|
407
|
+
# endless_scroll: bool = True
|
408
|
+
#
|
409
|
+
# def __post_init__(self):
|
410
|
+
# assert self.page is not None or self.ui_filter is not None, _(
|
411
|
+
# 'Argument page or ui_filter must be supplied'
|
412
|
+
# )
|
413
|
+
# if self.ui_filter and not self.page:
|
414
|
+
# self.page = self.ui_filter.get_page()
|
415
|
+
# super().__post_init__()
|
416
|
+
#
|
417
|
+
# def _has_panel(self) -> bool:
|
418
|
+
# return bool(self.panel_template or self.ui_filter)
|
419
|
+
#
|
420
|
+
#
|
421
|
+
# @dataclass(kw_only=True)
|
422
|
+
# class ListResponse(PageResponse):
|
423
|
+
#
|
424
|
+
# list_entry_template: str = None
|
425
|
+
# column_count: int = 1
|
426
|
+
# column_height: str = '150px'
|
427
|
+
# overview_data_template:str = 'ui/list.html'
|
428
|
+
#
|
429
|
+
#
|
430
|
+
# @dataclass(kw_only=True)
|
431
|
+
# class ListEntryResponse(Response):
|
432
|
+
#
|
433
|
+
# object: Model
|
434
|
+
# list_entry_template: str
|
435
|
+
# page: paginator.Page = None
|
436
|
+
# new_entry: bool = False
|
437
|
+
# template: str = 'ui/list_update.html'
|
438
|
+
#
|
439
|
+
# def render(self, request) -> str:
|
440
|
+
# res = super().render(request)
|
441
|
+
# if self.page:
|
442
|
+
# pagination_update = OobResponse(
|
443
|
+
# template='ui/layout.html#pagination',
|
444
|
+
# swap='innerHTML:#pagination',
|
445
|
+
# context=dict(page=self.page)
|
446
|
+
# ).render(request)
|
447
|
+
# res += pagination_update
|
448
|
+
# return res
|
449
|
+
#
|
450
|
+
#
|
451
|
+
# @dataclass(kw_only=True)
|
452
|
+
# class TableResponse(PageResponse):
|
453
|
+
#
|
454
|
+
# object_label: str
|
455
|
+
# fields: list[str]
|
456
|
+
# footer: dict = field(default_factory=dict)
|
457
|
+
# template = 'ui/table.html'
|
458
|
+
#
|
459
|
+
#
|
460
|
+
# @dataclass(kw_only=True)
|
461
|
+
# class TableRowResponse(Response):
|
462
|
+
#
|
463
|
+
# object: Model
|
464
|
+
# fields: list[str]
|
465
|
+
# footer: dict = field(default_factory=dict)
|
466
|
+
# page: paginator.Page = None
|
467
|
+
#
|
468
|
+
# base_template = 'ui/table_row_update.html'
|
469
|
+
#
|
470
|
+
#
|
471
|
+
# @dataclass(kw_only=True)
|
472
|
+
# class DetailResponse(Response):
|
473
|
+
#
|
474
|
+
# detail_data_template: str = None
|
475
|
+
# detail_header_template: str = None
|
476
|
+
#
|
477
|
+
# base_template = 'ui/detail.html'
|
478
|
+
#
|
479
|
+
# @staticmethod
|
480
|
+
# def add_trigger(response):
|
481
|
+
# add_trigger(response, 'activate-detail')
|
482
|
+
#
|
483
|
+
#
|
484
|
+
# @dataclass(kw_only=True)
|
485
|
+
# class ModalResponse(Response):
|
486
|
+
#
|
487
|
+
# title: str
|
488
|
+
# modal_id: str
|
489
|
+
# template: str
|
490
|
+
# modal_update: bool = False
|
491
|
+
# blocking: bool = False
|
492
|
+
# modal_width: str = None
|
493
|
+
#
|
494
|
+
# def __post_init__(self):
|
495
|
+
# super().__post_init__()
|
496
|
+
# self.modal_id = re.sub(r'[^A-Za-z-]+', '', self.modal_id).strip('-')
|
497
|
+
|
498
|
+
|
499
|
+
def search_select_response(queryset) -> HttpResponse:
|
500
|
+
return HttpResponse(render_to_string(
|
501
|
+
'ui/widgets/model_search_select_options.html',
|
502
|
+
{'options': queryset}
|
503
|
+
))
|
504
|
+
|
505
|
+
|
506
|
+
def message_response(request, persistent: bool = False):
|
507
|
+
return HttpResponse(content=(render_to_string(
|
508
|
+
'ui/message.html', context={'persistent': persistent}, request=request
|
509
|
+
)))
|
510
|
+
|
511
|
+
|
512
|
+
def add_trigger(
|
513
|
+
response: HttpResponse,
|
514
|
+
trigger: dict | str,
|
515
|
+
header: str = 'HX-Trigger'
|
516
|
+
) -> HttpResponse:
|
517
|
+
if isinstance(trigger, str):
|
518
|
+
trigger = {trigger: ''}
|
519
|
+
res_trigger = response.headers.get(header)
|
520
|
+
if not res_trigger:
|
521
|
+
response.headers[header] = json.dumps(trigger)
|
522
|
+
return response
|
523
|
+
try:
|
524
|
+
res_trigger = ast.literal_eval(response.headers.get(header, '{}'))
|
525
|
+
except SyntaxError:
|
526
|
+
res_trigger = {response.headers[header]: ''}
|
527
|
+
res_trigger.update(trigger)
|
528
|
+
response.headers[header] = json.dumps(res_trigger)
|
529
|
+
return response
|
530
|
+
|
531
|
+
|
532
|
+
def update(request, ui_responses: list[Response]) -> HttpResponse:
|
533
|
+
response = HttpResponse()
|
534
|
+
content = ''
|
535
|
+
for res in ui_responses:
|
536
|
+
content += res.render(request)
|
537
|
+
res.add_trigger(response)
|
538
|
+
content += render_to_string('ui/message.html', request=request)
|
539
|
+
response.content = content
|
540
|
+
return response
|