dynamicforms 0.76.14__py3-none-any.whl
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.
- dynamicforms/__init__.py +8 -0
- dynamicforms/action.py +521 -0
- dynamicforms/apps.py +5 -0
- dynamicforms/fields.py +1570 -0
- dynamicforms/filters.py +44 -0
- dynamicforms/locale/en/LC_MESSAGES/django.po +67 -0
- dynamicforms/locale/en/LC_MESSAGES/djangojs.po +31 -0
- dynamicforms/locale/sl/LC_MESSAGES/django.po +71 -0
- dynamicforms/locale/sl/LC_MESSAGES/djangojs.po +36 -0
- dynamicforms/management/__init__.py +0 -0
- dynamicforms/management/commands/__init__.py +0 -0
- dynamicforms/management/commands/clean_dfpreuploaded_files.py +26 -0
- dynamicforms/migrations/__init__.py +0 -0
- dynamicforms/mixins/__init__.py +27 -0
- dynamicforms/mixins/action.py +14 -0
- dynamicforms/mixins/choice/__init__.py +94 -0
- dynamicforms/mixins/choice/allow_tags.py +79 -0
- dynamicforms/mixins/choice/null_choice.py +26 -0
- dynamicforms/mixins/choice/single_choice.py +21 -0
- dynamicforms/mixins/color_field.py +4 -0
- dynamicforms/mixins/conditional_visibility.py +193 -0
- dynamicforms/mixins/enable_copy.py +4 -0
- dynamicforms/mixins/field_render.py +209 -0
- dynamicforms/mixins/file_field.py +5 -0
- dynamicforms/mixins/help_text.py +46 -0
- dynamicforms/mixins/implicit_hidden.py +7 -0
- dynamicforms/mixins/implicit_natural_date.py +88 -0
- dynamicforms/mixins/null_value.py +15 -0
- dynamicforms/mixins/password_field.py +23 -0
- dynamicforms/mixins/related_field_ajax.py +142 -0
- dynamicforms/mixins/rtf_field.py +58 -0
- dynamicforms/models.py +5 -0
- dynamicforms/models_utils.py +33 -0
- dynamicforms/pagination.py +175 -0
- dynamicforms/preupload_files.py +42 -0
- dynamicforms/progress.py +71 -0
- dynamicforms/renderers.py +1 -0
- dynamicforms/routers.py +36 -0
- dynamicforms/serializers.py +486 -0
- dynamicforms/struct.py +40 -0
- dynamicforms/template_render/__init__.py +10 -0
- dynamicforms/template_render/layout.py +178 -0
- dynamicforms/template_render/mixins/__init__.py +0 -0
- dynamicforms/template_render/mixins/base.py +39 -0
- dynamicforms/template_render/mixins/field.py +74 -0
- dynamicforms/template_render/mixins/listserializer.py +100 -0
- dynamicforms/template_render/mixins/render_mode_enum.py +8 -0
- dynamicforms/template_render/mixins/serializer.py +301 -0
- dynamicforms/template_render/mixins/serializer_filter.py +19 -0
- dynamicforms/template_render/mixins/serializer_render_actions.py +21 -0
- dynamicforms/template_render/mixins/serializer_render_fields.py +57 -0
- dynamicforms/template_render/mixins/util.py +9 -0
- dynamicforms/template_render/renderer.py +38 -0
- dynamicforms/template_render/responsive_table_layout.py +64 -0
- dynamicforms/urls.py +9 -0
- dynamicforms/utils.py +32 -0
- dynamicforms/views.py +1 -0
- dynamicforms/viewsets.py +421 -0
- dynamicforms-0.76.14.dist-info/METADATA +129 -0
- dynamicforms-0.76.14.dist-info/RECORD +287 -0
- dynamicforms-0.76.14.dist-info/WHEEL +4 -0
- dynamicforms-0.76.14.dist-info/licenses/LICENSE +21 -0
- dynamicforms_legacy/__init__.py +8 -0
- dynamicforms_legacy/action.py +561 -0
- dynamicforms_legacy/apps.py +5 -0
- dynamicforms_legacy/context_processors.py +27 -0
- dynamicforms_legacy/dynamicforms_migration_mixin.py +42 -0
- dynamicforms_legacy/fields.py +1108 -0
- dynamicforms_legacy/filters.py +44 -0
- dynamicforms_legacy/migrations/__init__.py +0 -0
- dynamicforms_legacy/mixins/__init__.py +16 -0
- dynamicforms_legacy/mixins/action.py +14 -0
- dynamicforms_legacy/mixins/allow_tags.py +85 -0
- dynamicforms_legacy/mixins/enable_copy.py +4 -0
- dynamicforms_legacy/mixins/file_field.py +5 -0
- dynamicforms_legacy/mixins/help_text.py +38 -0
- dynamicforms_legacy/mixins/implicit_hidden.py +7 -0
- dynamicforms_legacy/mixins/implicit_natural_date.py +86 -0
- dynamicforms_legacy/mixins/null_choice.py +26 -0
- dynamicforms_legacy/mixins/null_value.py +15 -0
- dynamicforms_legacy/mixins/password_field.py +19 -0
- dynamicforms_legacy/mixins/related_field_ajax.py +58 -0
- dynamicforms_legacy/mixins/render.py +203 -0
- dynamicforms_legacy/mixins/rtf_field.py +52 -0
- dynamicforms_legacy/mixins/single_choice.py +21 -0
- dynamicforms_legacy/models.py +5 -0
- dynamicforms_legacy/pagination.py +168 -0
- dynamicforms_legacy/progress.py +71 -0
- dynamicforms_legacy/renderers.py +183 -0
- dynamicforms_legacy/serializers.py +335 -0
- dynamicforms_legacy/settings.py +196 -0
- dynamicforms_legacy/static/bootstrap-3.4.1-dist/css/bootstrap-theme.css +587 -0
- dynamicforms_legacy/static/bootstrap-3.4.1-dist/css/bootstrap-theme.css.map +1 -0
- dynamicforms_legacy/static/bootstrap-3.4.1-dist/css/bootstrap-theme.min.css +6 -0
- dynamicforms_legacy/static/bootstrap-3.4.1-dist/css/bootstrap-theme.min.css.map +1 -0
- dynamicforms_legacy/static/bootstrap-3.4.1-dist/css/bootstrap.css +6834 -0
- dynamicforms_legacy/static/bootstrap-3.4.1-dist/css/bootstrap.css.map +1 -0
- dynamicforms_legacy/static/bootstrap-3.4.1-dist/css/bootstrap.min.css +6 -0
- dynamicforms_legacy/static/bootstrap-3.4.1-dist/css/bootstrap.min.css.map +1 -0
- dynamicforms_legacy/static/bootstrap-3.4.1-dist/fonts/glyphicons-halflings-regular.eot +0 -0
- dynamicforms_legacy/static/bootstrap-3.4.1-dist/fonts/glyphicons-halflings-regular.svg +288 -0
- dynamicforms_legacy/static/bootstrap-3.4.1-dist/fonts/glyphicons-halflings-regular.ttf +0 -0
- dynamicforms_legacy/static/bootstrap-3.4.1-dist/fonts/glyphicons-halflings-regular.woff +0 -0
- dynamicforms_legacy/static/bootstrap-3.4.1-dist/fonts/glyphicons-halflings-regular.woff2 +0 -0
- dynamicforms_legacy/static/bootstrap-3.4.1-dist/js/bootstrap.js +2580 -0
- dynamicforms_legacy/static/bootstrap-3.4.1-dist/js/bootstrap.min.js +6 -0
- dynamicforms_legacy/static/bootstrap-3.4.1-dist/js/npm.js +13 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap-grid.css +3719 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap-grid.css.map +1 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap-grid.min.css +7 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap-grid.min.css.map +1 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap-reboot.css +331 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap-reboot.css.map +1 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap-reboot.min.css +8 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap-reboot.min.css.map +1 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap.css +10038 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap.css.map +1 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap.min.css +7 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap.min.css.map +1 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/js/bootstrap.bundle.js +7013 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/js/bootstrap.bundle.js.map +1 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/js/bootstrap.bundle.min.js +7 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/js/bootstrap.bundle.min.js.map +1 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/js/bootstrap.js +4435 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/js/bootstrap.js.map +1 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/js/bootstrap.min.js +7 -0
- dynamicforms_legacy/static/bootstrap-4.3.1-dist/js/bootstrap.min.js.map +1 -0
- dynamicforms_legacy/static/ckeditor-df/ckEditorCustomBuildReadMe.txt +255 -0
- dynamicforms_legacy/static/ckeditor-df/ckeditor.js +6 -0
- dynamicforms_legacy/static/dynamicforms/dynamicforms.js +1883 -0
- dynamicforms_legacy/static/dynamicforms/icons/copy.svg +7 -0
- dynamicforms_legacy/static/dynamicforms/icons/eye-off-outline.svg +10 -0
- dynamicforms_legacy/static/dynamicforms/icons/eye-outline.svg +7 -0
- dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_222222_256x240.png +0 -0
- dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_228ef1_256x240.png +0 -0
- dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_ef8c08_256x240.png +0 -0
- dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_ffd27a_256x240.png +0 -0
- dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_ffffff_256x240.png +0 -0
- dynamicforms_legacy/static/jquery_ui/css/jquery-ui.min.css +7 -0
- dynamicforms_legacy/static/jquery_ui/css/jquery-ui.structure.min.css +5 -0
- dynamicforms_legacy/static/jquery_ui/css/jquery-ui.theme.min.css +5 -0
- dynamicforms_legacy/static/jquery_ui/js/jquery-3.3.1.min.js +2 -0
- dynamicforms_legacy/static/jquery_ui/js/jquery-ui.min.js +13 -0
- dynamicforms_legacy/static/select2/css/select2-bootstrap3.min.css +7 -0
- dynamicforms_legacy/static/select2/css/select2-bootstrap4.min.css +578 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/css/select2.min.css +1 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/af.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ar.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/az.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/bg.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/bs.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ca.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/cs.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/da.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/de.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/dsb.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/el.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/en.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/es.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/et.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/eu.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/fa.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/fi.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/fr.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/gl.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/he.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/hi.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/hr.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/hsb.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/hu.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/hy.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/id.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/is.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/it.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ja.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/km.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ko.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/lt.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/lv.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/mk.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ms.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/nb.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/nl.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/pl.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ps.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/pt-BR.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/pt.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ro.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ru.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/sk.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/sl.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/sr-Cyrl.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/sr.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/sv.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/th.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/tr.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/uk.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/vi.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/zh-CN.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/zh-TW.js +3 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/select2.full.js +6457 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/select2.full.min.js +1 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/select2.js +5746 -0
- dynamicforms_legacy/static/select2/select2-4.0.5/js/select2.min.js +1 -0
- dynamicforms_legacy/struct.py +40 -0
- dynamicforms_legacy/templates/dynamicforms/base.html +12 -0
- dynamicforms_legacy/templates/dynamicforms/base_form.html +44 -0
- dynamicforms_legacy/templates/dynamicforms/base_includes.html +51 -0
- dynamicforms_legacy/templates/dynamicforms/base_includes_select2.html +6 -0
- dynamicforms_legacy/templates/dynamicforms/base_list.html +47 -0
- dynamicforms_legacy/templates/dynamicforms/base_table_body.html +46 -0
- dynamicforms_legacy/templates/dynamicforms/base_table_filter.html +44 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/base_form.html +10 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/base_includes.html +46 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/base_includes_v3.html +90 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/base_includes_v4.html +77 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/base_list.html +9 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/base_table_body.html +4 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/base_table_filter.html +5 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/field/base_field.html +41 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/field/base_field_v3.html +11 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/field/base_field_v4.html +11 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/field/checkbox.html +7 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/field/checkbox_multiple.html +7 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/field/fieldset.html +21 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/field/form.html +4 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/field/input.html +31 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/field/list_fieldset.html +18 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/field/radio.html +8 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/field/rtf_field.html +4 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/field/select.html +46 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/field/select_multiple.html +17 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/field/textarea.html +4 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/modal_dialog.html +13 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/modal_dialog_rest.html +23 -0
- dynamicforms_legacy/templates/dynamicforms/bootstrap/page.html +11 -0
- dynamicforms_legacy/templates/dynamicforms/field/base_field.html +55 -0
- dynamicforms_legacy/templates/dynamicforms/field/checkbox.html +28 -0
- dynamicforms_legacy/templates/dynamicforms/field/checkbox_multiple.html +16 -0
- dynamicforms_legacy/templates/dynamicforms/field/dict_field.html +4 -0
- dynamicforms_legacy/templates/dynamicforms/field/fieldset.html +4 -0
- dynamicforms_legacy/templates/dynamicforms/field/form.html +18 -0
- dynamicforms_legacy/templates/dynamicforms/field/input.html +31 -0
- dynamicforms_legacy/templates/dynamicforms/field/list_field.html +4 -0
- dynamicforms_legacy/templates/dynamicforms/field/list_fieldset.html +4 -0
- dynamicforms_legacy/templates/dynamicforms/field/radio.html +24 -0
- dynamicforms_legacy/templates/dynamicforms/field/rtf_field.html +14 -0
- dynamicforms_legacy/templates/dynamicforms/field/select.html +97 -0
- dynamicforms_legacy/templates/dynamicforms/field/select_multiple.html +67 -0
- dynamicforms_legacy/templates/dynamicforms/field/textarea.html +13 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/base_form.html +13 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/base_includes.html +225 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/base_list.html +9 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/base_table_body.html +4 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/base_table_filter.html +5 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/base_field.html +16 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/checkbox.html +7 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/checkbox_multiple.html +9 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/fieldset.html +11 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/form.html +4 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/input.html +17 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/list_fieldset.html +6 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/radio.html +8 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/rtf_field.html +4 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/select.html +37 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/select_multiple.html +18 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/textarea.html +4 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/modal_dialog.html +2 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/modal_dialog_rest.html +27 -0
- dynamicforms_legacy/templates/dynamicforms/jquery_ui/page.html +20 -0
- dynamicforms_legacy/templates/dynamicforms/modal_dialog.html +4 -0
- dynamicforms_legacy/templates/dynamicforms/modal_dialog_rest.html +18 -0
- dynamicforms_legacy/templates/dynamicforms/page.html +25 -0
- dynamicforms_legacy/templates/dynamicforms/rtf_field_style.html +41 -0
- dynamicforms_legacy/templatetags/__init__.py +0 -0
- dynamicforms_legacy/templatetags/dynamicforms.py +475 -0
- dynamicforms_legacy/urls.py +8 -0
- dynamicforms_legacy/views.py +1 -0
- dynamicforms_legacy/viewsets.py +366 -0
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
import uuid as uuid_module
|
|
2
|
+
|
|
3
|
+
from enum import IntEnum
|
|
4
|
+
from typing import Iterable, List, Union
|
|
5
|
+
|
|
6
|
+
from django.utils.translation import gettext_lazy as _
|
|
7
|
+
from rest_framework.serializers import Serializer
|
|
8
|
+
|
|
9
|
+
from .settings import DYNAMICFORMS
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ActionBase(object):
|
|
13
|
+
def __init__(self, action_js: str, name: Union[str, None] = None, serializer: Serializer = None):
|
|
14
|
+
"""
|
|
15
|
+
:param action_js: JavaScript to execute when action is run
|
|
16
|
+
:param name: name by which to recognise this action in further processing, e.g. Serializer.suppress_action
|
|
17
|
+
:param serializer: bind to this serializer instance
|
|
18
|
+
"""
|
|
19
|
+
self.name = name
|
|
20
|
+
self.action_js = action_js
|
|
21
|
+
assert self.action_js is not None, "When declaring action, it must declare action JavaScript to execute"
|
|
22
|
+
# serializer will be set when obtaining a resolved copy
|
|
23
|
+
self.serializer = serializer
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
def action_id(self):
|
|
27
|
+
return id(self)
|
|
28
|
+
|
|
29
|
+
def copy_and_resolve_reference(self, serializer):
|
|
30
|
+
raise NotImplementedError()
|
|
31
|
+
|
|
32
|
+
def render(self, serializer: Serializer, **kwds):
|
|
33
|
+
raise NotImplementedError()
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def prepare_string(string, encode=True):
|
|
37
|
+
"""
|
|
38
|
+
Replaces curly brackets with some special string so there is no problem when string.format() is called
|
|
39
|
+
|
|
40
|
+
:param string: String in which program searches for curly brackets
|
|
41
|
+
:param encode: True: replaces brackets with special string, False: the other way around
|
|
42
|
+
:return:
|
|
43
|
+
"""
|
|
44
|
+
if not string:
|
|
45
|
+
return ""
|
|
46
|
+
replaces = {"{": "´|curl_brack_start|`", "}": "´|curl_brack_end|`"}
|
|
47
|
+
if not encode:
|
|
48
|
+
replaces = dict([(value, key) for key, value in replaces.items()])
|
|
49
|
+
|
|
50
|
+
for key, val in replaces.items():
|
|
51
|
+
string = string.replace(key, val)
|
|
52
|
+
return string
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class RenderableActionMixin(object):
|
|
56
|
+
"""
|
|
57
|
+
Action that is rendered on screen
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
def __init__(self, label: str, title: str, icon: str = None, btn_classes: Union[str, dict, None] = None):
|
|
61
|
+
"""
|
|
62
|
+
:param label: Label for rendering to on screen control
|
|
63
|
+
:param title: Hint text for on-screen control
|
|
64
|
+
:param icon: optional icon to add to render
|
|
65
|
+
:param btn_classes: optional class(es) of button. if variable is dict and key 'replace' have value True,
|
|
66
|
+
then default class will be replaced with class(es) that are under key 'classes'. In other case class(es) will
|
|
67
|
+
be just added to default class
|
|
68
|
+
"""
|
|
69
|
+
self.label = label
|
|
70
|
+
self.title = title
|
|
71
|
+
self.icon = icon
|
|
72
|
+
self.btn_classes = btn_classes
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class TablePosition(IntEnum):
|
|
76
|
+
HEADER = 0 # Table header of list view
|
|
77
|
+
FILTER_ROW_START = 7 # Alternative to HEADER: command is placed in filter row, actions column at start of line
|
|
78
|
+
FILTER_ROW_END = 8 # Alternative to HEADER: command is placed in filter row, actions column at end of line
|
|
79
|
+
# On left click on table row (currently this renders only once per table.
|
|
80
|
+
# We might need to add one that renders for each row
|
|
81
|
+
ROW_CLICK = 1
|
|
82
|
+
ROW_RIGHTCLICK = 2 # On right click on table row
|
|
83
|
+
ROW_START = 3 # Additional control column on left side of table
|
|
84
|
+
ROW_END = 4 # Additional control column on right side of table
|
|
85
|
+
FIELD_START = 5 # On left side of field value
|
|
86
|
+
FIELD_END = 6 # On right side of field value
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class TableAction(ActionBase, RenderableActionMixin):
|
|
90
|
+
def __init__(
|
|
91
|
+
self,
|
|
92
|
+
position: TablePosition,
|
|
93
|
+
label: str,
|
|
94
|
+
action_js: str,
|
|
95
|
+
title: Union[str, None] = None,
|
|
96
|
+
icon: Union[str, None] = None,
|
|
97
|
+
field_name: Union[str, None] = None,
|
|
98
|
+
name: Union[str, None] = None,
|
|
99
|
+
serializer: Serializer = None,
|
|
100
|
+
btn_classes: Union[str, dict, None] = None,
|
|
101
|
+
):
|
|
102
|
+
ActionBase.__init__(self, action_js, name, serializer)
|
|
103
|
+
RenderableActionMixin.__init__(self, label, title, icon, btn_classes)
|
|
104
|
+
self.position = position
|
|
105
|
+
self.field_name = field_name
|
|
106
|
+
|
|
107
|
+
def copy_and_resolve_reference(self, serializer: Serializer):
|
|
108
|
+
return TableAction(
|
|
109
|
+
self.position,
|
|
110
|
+
self.label,
|
|
111
|
+
self.action_js,
|
|
112
|
+
self.title,
|
|
113
|
+
self.icon,
|
|
114
|
+
self.field_name,
|
|
115
|
+
self.name,
|
|
116
|
+
serializer,
|
|
117
|
+
self.btn_classes,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
def render(self, serializer: Serializer, **kwds):
|
|
121
|
+
ret = rowclick = rowrclick = ""
|
|
122
|
+
stop_propagation = "dynamicforms.stopEventPropagation(event);"
|
|
123
|
+
|
|
124
|
+
action_action = self.prepare_string(self.action_js)
|
|
125
|
+
if self.position != TablePosition.HEADER:
|
|
126
|
+
# We need to do this differently because of dynamic page loading for tables: each time the serializer
|
|
127
|
+
# has a different UUID
|
|
128
|
+
action_action = action_action.replace(
|
|
129
|
+
"__TABLEID__", "$(event.target).parents('table').attr('id').substr(5)"
|
|
130
|
+
)
|
|
131
|
+
else:
|
|
132
|
+
action_action = action_action.replace("__TABLEID__", "'" + str(serializer.uuid) + "'")
|
|
133
|
+
|
|
134
|
+
if self.position == TablePosition.ROW_CLICK:
|
|
135
|
+
rowclick = action_action
|
|
136
|
+
elif self.position == TablePosition.ROW_RIGHTCLICK:
|
|
137
|
+
rowrclick = action_action
|
|
138
|
+
else:
|
|
139
|
+
from uuid import uuid1
|
|
140
|
+
|
|
141
|
+
def get_btn_class(default_class, additional_class):
|
|
142
|
+
classes = default_class.split(" ")
|
|
143
|
+
if additional_class:
|
|
144
|
+
if isinstance(additional_class, dict):
|
|
145
|
+
if additional_class.get("replace", False):
|
|
146
|
+
classes = []
|
|
147
|
+
additional_class = additional_class.get("classes", "").split(" ")
|
|
148
|
+
else:
|
|
149
|
+
additional_class = additional_class.split(" ")
|
|
150
|
+
classes.extend(additional_class)
|
|
151
|
+
return " ".join(classes)
|
|
152
|
+
|
|
153
|
+
button_name = (' name="btn-%s" ' % self.name) if self.name else ""
|
|
154
|
+
btn_class = get_btn_class("btn btn-info", self.btn_classes)
|
|
155
|
+
|
|
156
|
+
btnid = uuid1()
|
|
157
|
+
ret += (
|
|
158
|
+
'<button id="df-action-btn-{btnid}" type="button" class="{btn_class}" title="{title}"{button_name}'
|
|
159
|
+
'onClick="{stop_propagation} {action}">{icon_def}{label}</button>'.format(
|
|
160
|
+
btnid=btnid,
|
|
161
|
+
stop_propagation=stop_propagation,
|
|
162
|
+
action=action_action,
|
|
163
|
+
btn_class=btn_class,
|
|
164
|
+
label=self.prepare_string(self.label),
|
|
165
|
+
title=self.prepare_string(self.title),
|
|
166
|
+
icon_def='<img src="{icon}"/>'.format(icon=self.icon) if self.icon else "",
|
|
167
|
+
button_name=button_name,
|
|
168
|
+
)
|
|
169
|
+
)
|
|
170
|
+
if DYNAMICFORMS.jquery_ui:
|
|
171
|
+
ret += '<script type="application/javascript">$("#df-action-btn-{btnid}").button();</script>'.format(
|
|
172
|
+
btnid=btnid
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
if self.position in (TablePosition.ROW_CLICK, TablePosition.ROW_RIGHTCLICK):
|
|
176
|
+
if rowclick != "":
|
|
177
|
+
ret += (
|
|
178
|
+
"$('#list-{uuid}').find('tbody').click("
|
|
179
|
+
"function(event) {{ \n{stop_propagation} \n{action} \nreturn false;\n}});\n".format(
|
|
180
|
+
stop_propagation=stop_propagation, action=rowclick, uuid=serializer.uuid
|
|
181
|
+
)
|
|
182
|
+
)
|
|
183
|
+
if rowrclick != "":
|
|
184
|
+
ret += (
|
|
185
|
+
"$('#list-{uuid}').find('tbody').contextmenu("
|
|
186
|
+
"function(event) {{ \n{stop_propagation} \n{action} \nreturn false;\n}});\n".format(
|
|
187
|
+
stop_propagation=stop_propagation, action=rowrclick, uuid=serializer.uuid
|
|
188
|
+
)
|
|
189
|
+
)
|
|
190
|
+
if ret != "":
|
|
191
|
+
ret = '<script type="application/javascript">%s</script>' % ret
|
|
192
|
+
|
|
193
|
+
elif ret != "":
|
|
194
|
+
ret = '<div class="dynamicforms-actioncontrol float-{direction} pull-{direction}">{ret}</div>'.format(
|
|
195
|
+
ret=ret, direction="left" if self.position == TablePosition.FIELD_START else "right"
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
return self.prepare_string(ret, False)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class FieldChangeAction(ActionBase):
|
|
202
|
+
def __init__(
|
|
203
|
+
self,
|
|
204
|
+
tracked_fields: Iterable[str],
|
|
205
|
+
action_js: str,
|
|
206
|
+
name: Union[str, None] = None,
|
|
207
|
+
serializer: Serializer = None,
|
|
208
|
+
):
|
|
209
|
+
super().__init__(action_js, name, serializer)
|
|
210
|
+
self.tracked_fields = tracked_fields
|
|
211
|
+
assert self.tracked_fields, "When declaring an action, it must track at least one form field"
|
|
212
|
+
if serializer:
|
|
213
|
+
self.tracked_fields = [self._resolve_reference(f) for f in self.tracked_fields]
|
|
214
|
+
|
|
215
|
+
def _resolve_reference(self, ref):
|
|
216
|
+
from .mixins import RenderMixin
|
|
217
|
+
|
|
218
|
+
if isinstance(ref, uuid_module.UUID):
|
|
219
|
+
return str(ref)
|
|
220
|
+
elif isinstance(ref, RenderMixin):
|
|
221
|
+
# TODO unit tests!!!
|
|
222
|
+
# TODO test what happens if the Field instance given is from another serializer
|
|
223
|
+
# TODO test what happens when Field instance is actually a Serializer (when should onchange trigger for it?)
|
|
224
|
+
return ref.uuid
|
|
225
|
+
elif isinstance(ref, str) and ref in self.serializer.fields:
|
|
226
|
+
return self.serializer.fields[ref].uuid
|
|
227
|
+
elif isinstance(ref, str) and "." in ref:
|
|
228
|
+
# This supports nested serializers and fields with . notation, e.g. master_serializer_field.child_field
|
|
229
|
+
f = self.serializer
|
|
230
|
+
for r in ref.split("."):
|
|
231
|
+
f = f.fields[r]
|
|
232
|
+
return f.uuid
|
|
233
|
+
raise Exception("Unknown reference type for Action tracked field (%r)" % ref)
|
|
234
|
+
|
|
235
|
+
def copy_and_resolve_reference(self, serializer: Serializer):
|
|
236
|
+
return FieldChangeAction(self.tracked_fields, self.action_js, self.name, serializer)
|
|
237
|
+
|
|
238
|
+
def render(self, serializer: Serializer, **kwds):
|
|
239
|
+
res = "var action_func{0.action_id} = {0.action_js};\n".format(self)
|
|
240
|
+
for tracked_field in self.tracked_fields:
|
|
241
|
+
res += (
|
|
242
|
+
"dynamicforms.registerFieldAction('{ser.uuid}', '{tracked_field}', action_func{s.action_id});\n".format(
|
|
243
|
+
ser=serializer, tracked_field=tracked_field, s=self
|
|
244
|
+
)
|
|
245
|
+
)
|
|
246
|
+
return res
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
class FormInitAction(ActionBase):
|
|
250
|
+
def copy_and_resolve_reference(self, serializer: Serializer):
|
|
251
|
+
return FormInitAction(self.action_js, self.name, serializer)
|
|
252
|
+
|
|
253
|
+
def render(self, serializer: Serializer, **kwds):
|
|
254
|
+
# we need window.setTimeout because at the time of form generation, the initial fields value collection
|
|
255
|
+
# hasn't been done yet
|
|
256
|
+
return "window.setTimeout(function() {{ {0.action_js} }}, 1);\n".format(self)
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
class FieldInitAction(FieldChangeAction):
|
|
260
|
+
def copy_and_resolve_reference(self, serializer: Serializer):
|
|
261
|
+
return FieldInitAction(self.tracked_fields, self.action_js, self.name, serializer)
|
|
262
|
+
|
|
263
|
+
def render(self, serializer: Serializer, **kwds):
|
|
264
|
+
# we need window.setTimeout because at the time of form generation, the initial fields value collection
|
|
265
|
+
# hasn't been done yet
|
|
266
|
+
return "window.setTimeout(function() {{ {0.action_js} }}, 1);;\n".format(self)
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
class FormButtonTypes(IntEnum):
|
|
270
|
+
CANCEL = 1
|
|
271
|
+
SUBMIT = 2
|
|
272
|
+
CUSTOM = 3
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
class FormButtonAction(ActionBase):
|
|
276
|
+
DEFAULT_LABELS = {
|
|
277
|
+
FormButtonTypes.CANCEL: _("Cancel"),
|
|
278
|
+
FormButtonTypes.SUBMIT: _("Save changes"),
|
|
279
|
+
FormButtonTypes.CUSTOM: _("Custom"),
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
def __init__(
|
|
283
|
+
self,
|
|
284
|
+
btn_type: FormButtonTypes,
|
|
285
|
+
label: str = None,
|
|
286
|
+
btn_classes: str = None,
|
|
287
|
+
action_js: str = None,
|
|
288
|
+
button_is_primary: bool = None,
|
|
289
|
+
positions: List[str] = None,
|
|
290
|
+
name: Union[str, None] = None,
|
|
291
|
+
serializer: Serializer = None,
|
|
292
|
+
):
|
|
293
|
+
super().__init__(action_js or False, name, serializer)
|
|
294
|
+
self.uuid = uuid_module.uuid1()
|
|
295
|
+
self.btn_type = btn_type
|
|
296
|
+
self.label = label or FormButtonAction.DEFAULT_LABELS[btn_type or FormButtonTypes.CUSTOM]
|
|
297
|
+
self.positions = positions or ["dialog", "form"]
|
|
298
|
+
|
|
299
|
+
if button_is_primary is None:
|
|
300
|
+
button_is_primary = btn_type == FormButtonTypes.SUBMIT
|
|
301
|
+
self.button_is_primary = button_is_primary
|
|
302
|
+
|
|
303
|
+
self.btn_classes = btn_classes or (
|
|
304
|
+
DYNAMICFORMS.form_button_classes
|
|
305
|
+
+ " "
|
|
306
|
+
+ (
|
|
307
|
+
DYNAMICFORMS.form_button_classes_primary
|
|
308
|
+
if button_is_primary
|
|
309
|
+
else DYNAMICFORMS.form_button_classes_secondary
|
|
310
|
+
)
|
|
311
|
+
+ " "
|
|
312
|
+
+ (DYNAMICFORMS.form_button_classes_cancel if btn_type == FormButtonTypes.CANCEL else "")
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
def copy_and_resolve_reference(self, serializer):
|
|
316
|
+
return FormButtonAction(
|
|
317
|
+
self.btn_type,
|
|
318
|
+
self.label,
|
|
319
|
+
self.btn_classes,
|
|
320
|
+
self.action_js,
|
|
321
|
+
self.button_is_primary,
|
|
322
|
+
self.positions,
|
|
323
|
+
self.name,
|
|
324
|
+
serializer,
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
def render(self, serializer: Serializer, position=None, **kwds):
|
|
328
|
+
if self.btn_type == FormButtonTypes.CANCEL and position == "form":
|
|
329
|
+
return ""
|
|
330
|
+
action_js = self.action_js
|
|
331
|
+
button_name = ('name="btn-%s"' % self.name) if self.name else ""
|
|
332
|
+
if isinstance(action_js, str):
|
|
333
|
+
action_js = self.prepare_string(action_js)
|
|
334
|
+
action_js = action_js.format(**locals())
|
|
335
|
+
button_type = "button" if self.btn_type != FormButtonTypes.SUBMIT or position == "dialog" else "submit"
|
|
336
|
+
data_dismiss = 'data-dismiss="modal"' if self.btn_type == FormButtonTypes.CANCEL else ""
|
|
337
|
+
if self.btn_type == FormButtonTypes.SUBMIT:
|
|
338
|
+
button_id = "save-" + str(serializer.uuid)
|
|
339
|
+
else:
|
|
340
|
+
button_id = "formbutton-" + str(self.uuid)
|
|
341
|
+
if (self.btn_type != FormButtonTypes.SUBMIT or position == "dialog") and action_js:
|
|
342
|
+
button_js = (
|
|
343
|
+
'<script type="text/javascript">'
|
|
344
|
+
' $("#{button_id}").on("click", function() {{'
|
|
345
|
+
" {action_js}"
|
|
346
|
+
" }});"
|
|
347
|
+
"</script>"
|
|
348
|
+
).format(**locals())
|
|
349
|
+
else:
|
|
350
|
+
button_js = ""
|
|
351
|
+
|
|
352
|
+
return self.prepare_string(
|
|
353
|
+
'<button type="{button_type}" class="{self.btn_classes}" {data_dismiss} {button_name} id="{button_id}">'
|
|
354
|
+
"{self.label}</button>{button_js}".format(**locals()),
|
|
355
|
+
False,
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
class Actions(object):
|
|
360
|
+
def __init__(
|
|
361
|
+
self, *args, add_default_crud: bool = False, add_default_filter: bool = False, add_form_buttons: bool = True
|
|
362
|
+
) -> None:
|
|
363
|
+
super().__init__()
|
|
364
|
+
if len(args) == 1 and args[0] is None:
|
|
365
|
+
self.actions = []
|
|
366
|
+
return
|
|
367
|
+
|
|
368
|
+
self.actions = list(args) # type: List[ActionBase]
|
|
369
|
+
if add_default_crud:
|
|
370
|
+
self.actions.append(
|
|
371
|
+
TableAction(
|
|
372
|
+
TablePosition.HEADER,
|
|
373
|
+
_("+ Add"),
|
|
374
|
+
title=_("Add new record"),
|
|
375
|
+
name="add",
|
|
376
|
+
action_js="dynamicforms.newRow('{% url url_reverse|add:'-detail' pk='new' format='html' %}'"
|
|
377
|
+
", 'record', __TABLEID__);",
|
|
378
|
+
)
|
|
379
|
+
)
|
|
380
|
+
self.actions.append(
|
|
381
|
+
TableAction(
|
|
382
|
+
TablePosition.ROW_CLICK,
|
|
383
|
+
_("Edit"),
|
|
384
|
+
title=_("Edit record"),
|
|
385
|
+
name="edit",
|
|
386
|
+
action_js="dynamicforms.editRow('{% url url_reverse|add:'-detail' pk='__ROWID__' "
|
|
387
|
+
"format='html' %}'.replace('__ROWID__', $(event.target.parentElement).closest("
|
|
388
|
+
"'tr[class=\"df-table-row\"]').attr('data-id')), 'record', __TABLEID__);",
|
|
389
|
+
)
|
|
390
|
+
)
|
|
391
|
+
self.actions.append(
|
|
392
|
+
TableAction(
|
|
393
|
+
TablePosition.ROW_END,
|
|
394
|
+
label=_("Delete"),
|
|
395
|
+
title=_("Delete record"),
|
|
396
|
+
name="delete",
|
|
397
|
+
action_js="dynamicforms.deleteRow('{% url url_reverse|add:'-detail' pk=row.id %}', "
|
|
398
|
+
"{{row.id}}, 'record', __TABLEID__);",
|
|
399
|
+
)
|
|
400
|
+
)
|
|
401
|
+
if add_default_filter:
|
|
402
|
+
self.actions.append(
|
|
403
|
+
TableAction(
|
|
404
|
+
TablePosition.HEADER,
|
|
405
|
+
label=_("Filter"),
|
|
406
|
+
title=_("Filter"),
|
|
407
|
+
name="filter",
|
|
408
|
+
action_js="dynamicforms.defaultFilter(event);",
|
|
409
|
+
)
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
if add_form_buttons:
|
|
413
|
+
self.actions.append(FormButtonAction(btn_type=FormButtonTypes.CANCEL, name="cancel"))
|
|
414
|
+
self.actions.append(FormButtonAction(btn_type=FormButtonTypes.SUBMIT, name="submit"))
|
|
415
|
+
|
|
416
|
+
def get_resolved_copy(self, serializer) -> "Actions":
|
|
417
|
+
"""
|
|
418
|
+
Returns a copy of declared actions bound to the serializer
|
|
419
|
+
:param serializer: serializer the copy will be bound to
|
|
420
|
+
:return:
|
|
421
|
+
"""
|
|
422
|
+
if not isinstance(serializer, Serializer):
|
|
423
|
+
return Actions(None)
|
|
424
|
+
|
|
425
|
+
actions = [a.copy_and_resolve_reference(serializer) for a in self.actions]
|
|
426
|
+
|
|
427
|
+
# move actions from Field to Serializer
|
|
428
|
+
actions.extend(
|
|
429
|
+
[
|
|
430
|
+
a.copy_and_resolve_reference(serializer)
|
|
431
|
+
for field in serializer.fields.values()
|
|
432
|
+
for a in getattr(field, "actions", Actions(None)).actions_not_suppressed(serializer)
|
|
433
|
+
if isinstance(a, FieldChangeAction)
|
|
434
|
+
]
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
return Actions(*actions, add_form_buttons=False)
|
|
438
|
+
|
|
439
|
+
def render_field_onchange(self, serializer):
|
|
440
|
+
"""
|
|
441
|
+
renders all field onchange actions needed for dynamicforms.registerFieldAction() function
|
|
442
|
+
|
|
443
|
+
:return: the actions rendered as template string
|
|
444
|
+
"""
|
|
445
|
+
res = ""
|
|
446
|
+
for action in self.actions:
|
|
447
|
+
if isinstance(action, FieldChangeAction) and not isinstance(action, FieldInitAction):
|
|
448
|
+
res += action.render(serializer)
|
|
449
|
+
return res
|
|
450
|
+
|
|
451
|
+
def render_form_init(self, serializer):
|
|
452
|
+
"""
|
|
453
|
+
renders the function which will analyse initial form data and hide appropriate fields
|
|
454
|
+
|
|
455
|
+
:return: the actions rendered as template string
|
|
456
|
+
"""
|
|
457
|
+
res = ""
|
|
458
|
+
for action in self.actions:
|
|
459
|
+
if isinstance(action, FormInitAction):
|
|
460
|
+
res += action.render(serializer)
|
|
461
|
+
return res
|
|
462
|
+
|
|
463
|
+
def render_field_init(self, serializer, field_name: str):
|
|
464
|
+
"""
|
|
465
|
+
renders function that will initialise the field being rendered
|
|
466
|
+
|
|
467
|
+
:return: the actions rendered as template string
|
|
468
|
+
"""
|
|
469
|
+
res = ""
|
|
470
|
+
for action in self.actions:
|
|
471
|
+
if isinstance(action, FieldInitAction) and field_name in action.tracked_fields:
|
|
472
|
+
res += action.render(serializer)
|
|
473
|
+
return res
|
|
474
|
+
|
|
475
|
+
def renderable_actions(self, serializer: Serializer):
|
|
476
|
+
request = serializer.context.get("request", None)
|
|
477
|
+
viewset = serializer.context.get("view", None)
|
|
478
|
+
return (
|
|
479
|
+
a
|
|
480
|
+
for a in self.actions
|
|
481
|
+
if isinstance(a, TableAction) and not serializer.suppress_action(a, request, viewset)
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
def render_renderable_actions(
|
|
485
|
+
self, allowed_positions: Iterable[TablePosition], field_name: str, serializer: Serializer
|
|
486
|
+
):
|
|
487
|
+
"""
|
|
488
|
+
Returns those actions that are not suppressed
|
|
489
|
+
:return: List[Action]
|
|
490
|
+
"""
|
|
491
|
+
res = ""
|
|
492
|
+
|
|
493
|
+
for action in self.renderable_actions(serializer):
|
|
494
|
+
if action.position in allowed_positions and (field_name is None or field_name == action.field_name):
|
|
495
|
+
res += action.render(serializer)
|
|
496
|
+
return res
|
|
497
|
+
|
|
498
|
+
def actions_not_suppressed(self, serializer: Serializer):
|
|
499
|
+
request = serializer.context.get("request", None)
|
|
500
|
+
viewset = serializer.context.get("view", None)
|
|
501
|
+
|
|
502
|
+
return (a for a in self.actions if not serializer.suppress_action(a, request, viewset))
|
|
503
|
+
|
|
504
|
+
def render_form_buttons(self, serializer: Serializer, position: str):
|
|
505
|
+
"""
|
|
506
|
+
Renders form buttons
|
|
507
|
+
:return: List[Action]
|
|
508
|
+
"""
|
|
509
|
+
request = serializer.context.get("request", None)
|
|
510
|
+
viewset = serializer.context.get("view", None)
|
|
511
|
+
|
|
512
|
+
res = ""
|
|
513
|
+
|
|
514
|
+
for button in self.actions:
|
|
515
|
+
if (
|
|
516
|
+
isinstance(button, FormButtonAction)
|
|
517
|
+
and position in button.positions
|
|
518
|
+
and not serializer.suppress_action(button, request, viewset)
|
|
519
|
+
):
|
|
520
|
+
res += button.render(serializer, position=position)
|
|
521
|
+
return res
|
|
522
|
+
|
|
523
|
+
def __iter__(self):
|
|
524
|
+
return iter(self.actions)
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
"""
|
|
528
|
+
tipi akcij
|
|
529
|
+
crud (new, edit, delete, view detail)
|
|
530
|
+
on field change
|
|
531
|
+
on form display (initial fields hiding)
|
|
532
|
+
dialog / form manipulation (cancel entry, submit entry)
|
|
533
|
+
custom actions
|
|
534
|
+
|
|
535
|
+
kako se akcije renderajo
|
|
536
|
+
gumb / link -> html control
|
|
537
|
+
onclick / onrightclick / onkey -> JS event
|
|
538
|
+
on field change -> JS event (depends on field / position)
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
akcije na formi / dialogu
|
|
542
|
+
control column (start, end of row, any position?) -> HTML control
|
|
543
|
+
table header / footer -> html control
|
|
544
|
+
table field left / right -> html control
|
|
545
|
+
form field left / right -> html control
|
|
546
|
+
form top, form bottom -> html control
|
|
547
|
+
custom pozicija (programer pokliče render funkcijo z nekim custom tekstom, namesto z enum vrednostjo)
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
ali morajo vedeti, na čem so?
|
|
552
|
+
pri formi imamo submit, pri dialogu pa dynamicforms.SubmitForm, se pravi, da je render drugačen
|
|
553
|
+
pri tabeli row id, morda row data?
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
podatki, ki so lahko na voljo:
|
|
557
|
+
parent serializer
|
|
558
|
+
serializer
|
|
559
|
+
row data
|
|
560
|
+
form data --> serializer
|
|
561
|
+
"""
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from django.http import HttpRequest
|
|
2
|
+
|
|
3
|
+
from .settings import DYNAMICFORMS
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def add_dynamicforms_settings(request: HttpRequest):
|
|
7
|
+
"""
|
|
8
|
+
context processor that adds DynamicForms configuration variables to template context
|
|
9
|
+
|
|
10
|
+
Example for supporting different versions of bootstrap:
|
|
11
|
+
|
|
12
|
+
.. code-block:: python
|
|
13
|
+
|
|
14
|
+
{% if DYNAMICFORMS.bootstrap_version == 'v3' %}
|
|
15
|
+
{% set_var card_class='panel panel-default' card_header='panel-heading' card_body='panel_body' %}
|
|
16
|
+
{% else %}
|
|
17
|
+
{% set_var card_class='card' card_header='card-header' card_body='card-body' %}
|
|
18
|
+
{% endif %}
|
|
19
|
+
|
|
20
|
+
.. note:: Using DynamicForms renderers automatically adds this variable into the context as it is required by
|
|
21
|
+
template packs.
|
|
22
|
+
|
|
23
|
+
:param request: see `django documentation <https://docs.djangoproject.com/en/dev/ref/templates/api/
|
|
24
|
+
#writing-your-own-context-processors>`_
|
|
25
|
+
:return: dict with `DYNAMICFORMS` context variable set
|
|
26
|
+
"""
|
|
27
|
+
return dict(DYNAMICFORMS=DYNAMICFORMS)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import random
|
|
2
|
+
|
|
3
|
+
import django.utils.timezone
|
|
4
|
+
|
|
5
|
+
from examples.models import Filter, PageLoad, Relation
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def add_relation(apps, schema_editor):
|
|
9
|
+
if not Relation.objects.all().count():
|
|
10
|
+
for i in range(1, 11):
|
|
11
|
+
Relation.objects.create(name="Relation object %d" % i)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def add_filter(apps, schema_editor):
|
|
15
|
+
if not Filter.objects.all().count():
|
|
16
|
+
date_now = django.utils.timezone.now()
|
|
17
|
+
char_field = ["abc", "def", "ghi", "abcdef", "abcghi", "defghi", "abcdefghi"]
|
|
18
|
+
for i in range(1, 100 + 1):
|
|
19
|
+
date_now = date_now + django.utils.timezone.timedelta(hours=3)
|
|
20
|
+
Filter.objects.create(
|
|
21
|
+
char_field="%s %d" % (char_field[(i - 1) % 7], i),
|
|
22
|
+
datetime_field=date_now,
|
|
23
|
+
int_field=((i - 1) % 10) + 1,
|
|
24
|
+
int_choice_field=((i - 1) % 4),
|
|
25
|
+
bool_field=((i - 1) % 10) > 4,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def add_page_load(apps, schema_editor):
|
|
30
|
+
if not PageLoad.objects.all().count():
|
|
31
|
+
for i in range(1, 10000 + 1):
|
|
32
|
+
PageLoad.objects.create(description="Item %d" % i, choice=random.randint(1, 4))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class DynamicformsMigrationMixin(object):
|
|
36
|
+
def apply(self, project_state, schema_editor, collect_sql=False):
|
|
37
|
+
applied = super().apply(project_state, schema_editor, collect_sql)
|
|
38
|
+
if "0003_filter_name" in self.name:
|
|
39
|
+
add_relation(None, None)
|
|
40
|
+
add_page_load(None, None)
|
|
41
|
+
add_filter(None, None)
|
|
42
|
+
return applied
|