├── .actrc ├── .coveragerc ├── .github └── workflows │ ├── Python tests.yml │ ├── check_code.yml │ ├── check_doc.yml │ ├── incremental-cover-check.yml │ └── vitest_tests.yml ├── .gitignore ├── LICENSE ├── MANIFEST.in ├── README.md ├── docs ├── .docs_archive │ ├── Makefile │ ├── conf.py │ ├── documents │ │ ├── api │ │ │ ├── action_controls.rst │ │ │ ├── context_processors.rst │ │ │ ├── dialogs.rst │ │ │ ├── fields.rst │ │ │ ├── index.rst │ │ │ ├── renderers.rst │ │ │ ├── serializers.rst │ │ │ ├── templatetags.rst │ │ │ └── viewsets.rst │ │ ├── contribute.rst │ │ ├── guides │ │ │ ├── index.rst │ │ │ ├── quick_start.rst │ │ │ └── templates.rst │ │ ├── intro.rst │ │ └── settings.rst │ ├── index.rst │ └── make.bat ├── .vitepress │ ├── config.mts │ └── theme │ │ ├── index.ts │ │ └── style.css ├── examples │ ├── api-examples.md │ └── markdown-examples.md ├── getting-started.md ├── index.md ├── reference │ ├── dialog-size.md │ ├── hiding_titlebar_and_navbar.md │ ├── index.md │ └── layout.md └── settings.md ├── dynamicforms ├── __init__.py ├── action.py ├── apps.py ├── fields.py ├── filters.py ├── int_choice_enum.py ├── locale │ ├── en │ │ └── LC_MESSAGES │ │ │ ├── django.po │ │ │ └── djangojs.po │ └── sl │ │ └── LC_MESSAGES │ │ ├── django.po │ │ └── djangojs.po ├── migrations │ └── __init__.py ├── mixins │ ├── __init__.py │ ├── action.py │ ├── choice │ │ ├── __init__.py │ │ ├── allow_tags.py │ │ ├── null_choice.py │ │ └── single_choice.py │ ├── color_field.py │ ├── conditional_visibility.py │ ├── enable_copy.py │ ├── field_render.py │ ├── file_field.py │ ├── help_text.py │ ├── implicit_hidden.py │ ├── implicit_natural_date.py │ ├── null_value.py │ ├── password_field.py │ ├── related_field_ajax.py │ └── rtf_field.py ├── models.py ├── models_fields.py ├── pagination.py ├── preupload_files.py ├── progress.py ├── renderers.py ├── routers.py ├── serializers.py ├── struct.py ├── template_render │ ├── __init__.py │ ├── layout.py │ ├── mixins │ │ ├── __init__.py │ │ ├── base.py │ │ ├── field.py │ │ ├── listserializer.py │ │ ├── render_mode_enum.py │ │ ├── serializer.py │ │ ├── serializer_filter.py │ │ ├── serializer_render_actions.py │ │ ├── serializer_render_fields.py │ │ └── util.py │ ├── renderer.py │ └── responsive_table_layout.py ├── urls.py ├── utils.py ├── views.py └── viewsets.py ├── dynamicforms_dev ├── __init__.py └── management │ ├── __init__.py │ └── commands │ ├── __init__.py │ ├── generate_fields.py │ └── npm_run.py ├── dynamicforms_legacy ├── __init__.py ├── action.py ├── apps.py ├── context_processors.py ├── dynamicforms_migration_mixin.py ├── fields.py ├── filters.py ├── migrations │ └── __init__.py ├── mixins │ ├── __init__.py │ ├── action.py │ ├── allow_tags.py │ ├── enable_copy.py │ ├── file_field.py │ ├── help_text.py │ ├── implicit_hidden.py │ ├── implicit_natural_date.py │ ├── null_choice.py │ ├── null_value.py │ ├── password_field.py │ ├── related_field_ajax.py │ ├── render.py │ ├── rtf_field.py │ └── single_choice.py ├── models.py ├── pagination.py ├── progress.py ├── renderers.py ├── serializers.py ├── settings.py ├── static │ ├── bootstrap-3.4.1-dist │ │ ├── css │ │ │ ├── bootstrap-theme.css │ │ │ ├── bootstrap-theme.css.map │ │ │ ├── bootstrap-theme.min.css │ │ │ ├── bootstrap-theme.min.css.map │ │ │ ├── bootstrap.css │ │ │ ├── bootstrap.css.map │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ └── js │ │ │ ├── bootstrap.js │ │ │ ├── bootstrap.min.js │ │ │ └── npm.js │ ├── bootstrap-4.3.1-dist │ │ ├── css │ │ │ ├── bootstrap-grid.css │ │ │ ├── bootstrap-grid.css.map │ │ │ ├── bootstrap-grid.min.css │ │ │ ├── bootstrap-grid.min.css.map │ │ │ ├── bootstrap-reboot.css │ │ │ ├── bootstrap-reboot.css.map │ │ │ ├── bootstrap-reboot.min.css │ │ │ ├── bootstrap-reboot.min.css.map │ │ │ ├── bootstrap.css │ │ │ ├── bootstrap.css.map │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ └── js │ │ │ ├── bootstrap.bundle.js │ │ │ ├── bootstrap.bundle.js.map │ │ │ ├── bootstrap.bundle.min.js │ │ │ ├── bootstrap.bundle.min.js.map │ │ │ ├── bootstrap.js │ │ │ ├── bootstrap.js.map │ │ │ ├── bootstrap.min.js │ │ │ └── bootstrap.min.js.map │ ├── ckeditor-df │ │ ├── ckEditorCustomBuildReadMe.txt │ │ └── ckeditor.js │ ├── dynamicforms │ │ ├── dynamicforms.js │ │ └── icons │ │ │ ├── copy.svg │ │ │ ├── eye-off-outline.svg │ │ │ └── eye-outline.svg │ ├── jquery_ui │ │ ├── css │ │ │ ├── images │ │ │ │ ├── ui-bg_diagonals-thick_18_b81900_40x40.png │ │ │ │ ├── ui-bg_diagonals-thick_20_666666_40x40.png │ │ │ │ ├── ui-bg_glass_100_f6f6f6_1x400.png │ │ │ │ ├── ui-bg_glass_100_fdf5ce_1x400.png │ │ │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ │ │ ├── ui-bg_gloss-wave_35_f6a828_500x100.png │ │ │ │ ├── ui-bg_highlight-soft_100_eeeeee_1x100.png │ │ │ │ ├── ui-bg_highlight-soft_75_ffe45c_1x100.png │ │ │ │ ├── ui-icons_222222_256x240.png │ │ │ │ ├── ui-icons_228ef1_256x240.png │ │ │ │ ├── ui-icons_ef8c08_256x240.png │ │ │ │ ├── ui-icons_ffd27a_256x240.png │ │ │ │ └── ui-icons_ffffff_256x240.png │ │ │ ├── jquery-ui.min.css │ │ │ ├── jquery-ui.structure.min.css │ │ │ └── jquery-ui.theme.min.css │ │ └── js │ │ │ ├── jquery-3.3.1.min.js │ │ │ └── jquery-ui.min.js │ └── select2 │ │ ├── css │ │ ├── select2-bootstrap3.min.css │ │ └── select2-bootstrap4.min.css │ │ └── select2-4.0.5 │ │ ├── css │ │ └── select2.min.css │ │ └── js │ │ ├── i18n │ │ ├── af.js │ │ ├── ar.js │ │ ├── az.js │ │ ├── bg.js │ │ ├── bs.js │ │ ├── ca.js │ │ ├── cs.js │ │ ├── da.js │ │ ├── de.js │ │ ├── dsb.js │ │ ├── el.js │ │ ├── en.js │ │ ├── es.js │ │ ├── et.js │ │ ├── eu.js │ │ ├── fa.js │ │ ├── fi.js │ │ ├── fr.js │ │ ├── gl.js │ │ ├── he.js │ │ ├── hi.js │ │ ├── hr.js │ │ ├── hsb.js │ │ ├── hu.js │ │ ├── hy.js │ │ ├── id.js │ │ ├── is.js │ │ ├── it.js │ │ ├── ja.js │ │ ├── km.js │ │ ├── ko.js │ │ ├── lt.js │ │ ├── lv.js │ │ ├── mk.js │ │ ├── ms.js │ │ ├── nb.js │ │ ├── nl.js │ │ ├── pl.js │ │ ├── ps.js │ │ ├── pt-BR.js │ │ ├── pt.js │ │ ├── ro.js │ │ ├── ru.js │ │ ├── sk.js │ │ ├── sl.js │ │ ├── sr-Cyrl.js │ │ ├── sr.js │ │ ├── sv.js │ │ ├── th.js │ │ ├── tr.js │ │ ├── uk.js │ │ ├── vi.js │ │ ├── zh-CN.js │ │ └── zh-TW.js │ │ ├── select2.full.js │ │ ├── select2.full.min.js │ │ ├── select2.js │ │ └── select2.min.js ├── struct.py ├── templates │ └── dynamicforms │ │ ├── base.html │ │ ├── base_form.html │ │ ├── base_includes.html │ │ ├── base_includes_select2.html │ │ ├── base_list.html │ │ ├── base_table_body.html │ │ ├── base_table_filter.html │ │ ├── bootstrap │ │ ├── base_form.html │ │ ├── base_includes.html │ │ ├── base_includes_v3.html │ │ ├── base_includes_v4.html │ │ ├── base_list.html │ │ ├── base_table_body.html │ │ ├── base_table_filter.html │ │ ├── field │ │ │ ├── base_field.html │ │ │ ├── base_field_v3.html │ │ │ ├── base_field_v4.html │ │ │ ├── checkbox.html │ │ │ ├── checkbox_multiple.html │ │ │ ├── fieldset.html │ │ │ ├── form.html │ │ │ ├── input.html │ │ │ ├── list_fieldset.html │ │ │ ├── radio.html │ │ │ ├── rtf_field.html │ │ │ ├── select.html │ │ │ ├── select_multiple.html │ │ │ └── textarea.html │ │ ├── modal_dialog.html │ │ ├── modal_dialog_rest.html │ │ └── page.html │ │ ├── field │ │ ├── base_field.html │ │ ├── checkbox.html │ │ ├── checkbox_multiple.html │ │ ├── dict_field.html │ │ ├── fieldset.html │ │ ├── form.html │ │ ├── input.html │ │ ├── list_field.html │ │ ├── list_fieldset.html │ │ ├── radio.html │ │ ├── rtf_field.html │ │ ├── select.html │ │ ├── select_multiple.html │ │ └── textarea.html │ │ ├── jquery_ui │ │ ├── base_form.html │ │ ├── base_includes.html │ │ ├── base_list.html │ │ ├── base_table_body.html │ │ ├── base_table_filter.html │ │ ├── field │ │ │ ├── base_field.html │ │ │ ├── checkbox.html │ │ │ ├── checkbox_multiple.html │ │ │ ├── fieldset.html │ │ │ ├── form.html │ │ │ ├── input.html │ │ │ ├── list_fieldset.html │ │ │ ├── radio.html │ │ │ ├── rtf_field.html │ │ │ ├── select.html │ │ │ ├── select_multiple.html │ │ │ └── textarea.html │ │ ├── modal_dialog.html │ │ ├── modal_dialog_rest.html │ │ └── page.html │ │ ├── modal_dialog.html │ │ ├── modal_dialog_rest.html │ │ ├── page.html │ │ └── rtf_field_style.html ├── templatetags │ ├── __init__.py │ └── dynamicforms.py ├── urls.py ├── views.py └── viewsets.py ├── examples ├── __init__.py ├── admin.py ├── apps.py ├── enum_field.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto_20190320_0823.py │ ├── 0003_filter_name.py │ ├── 0004_basicfields_password_field.py │ ├── 0005_advancedfields_file_field_two.py │ ├── 0005_refreshtype_rich_text_field.py │ ├── 0006_merge_20200921_1152.py │ ├── 0007_basicfields_nullint_field.py │ ├── 0008_auto_20210303_0904.py │ ├── 0008_auto_20210312_1146.py │ ├── 0009_auto_20210929_1136.py │ ├── 0010_filter_rtf_field.py │ ├── 0011_auto_20211120_0523.py │ ├── 0012_advancedfields_color_field_and_more.py │ └── __init__.py ├── models.py ├── recurrence_utils.py ├── rest │ ├── __init__.py │ ├── actions_overview.py │ ├── advanced_fields.py │ ├── basic_fields.py │ ├── calculated_css_class_for_table_row.py │ ├── calendar.py │ ├── calendar_dependencies.py │ ├── calendar_recurrence.py │ ├── calendar_reminders.py │ ├── choice_allow_tags_fields.py │ ├── document.py │ ├── fields │ │ ├── __init__.py │ │ └── name_field.py │ ├── filter.py │ ├── hidden_fields.py │ ├── page_load.py │ ├── relation.py │ ├── single_dialog.py │ ├── validated.py │ └── write_only_fields.py ├── tests.py └── urls.py ├── manage.py ├── package-lock.json ├── package.json ├── publish.py ├── pyproject.toml ├── readthedocs.yml ├── requirements.txt ├── requirements_test_functional.txt ├── setup ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py ├── tests ├── __init__.py ├── functional │ ├── __init__.py │ ├── _test_advanced_fields.py │ ├── _test_basic_fields.py │ ├── _test_filter.py │ ├── _test_hidden_fields.py │ ├── _test_page_load.py │ ├── _test_single_dialog.py │ ├── _test_validated.py │ ├── _tests.py │ ├── select.py │ └── selenium_test_case.py ├── request_sync.py ├── static_files │ └── 0_3142.prj └── unit │ ├── __init__.py │ ├── test_calendar.py │ ├── test_conditional_visibility.py │ ├── test_cursor_pagination.py │ ├── test_df_serializer.py │ ├── test_filter.py │ ├── test_page_load.py │ ├── test_struct.py │ ├── test_validate_allow_null_for_field_with_source_equal_to_star.py │ └── tests.py ├── tox.ini ├── tsconfig.build.json ├── tsconfig.eslint.json ├── tsconfig.json └── vue ├── demo ├── .env ├── .gitignore ├── index.html ├── package.json ├── src │ ├── demo-app │ │ ├── demo-app.vue │ │ ├── index.ts │ │ ├── modal-demo.vue │ │ ├── named-component-loader.vue │ │ └── vuetify │ │ │ ├── df-calendar.vue │ │ │ ├── form-consumer.vue │ │ │ ├── single-dialog.vue │ │ │ ├── view-mode.vue │ │ │ └── vuetify-app.vue │ ├── main.ts │ ├── plugins │ │ ├── dynamic-forms.ts │ │ └── vuetify.ts │ ├── router.ts │ └── routes.ts ├── tsconfig.json └── vite.config.ts └── dynamicforms ├── .gitignore ├── package.json ├── src ├── components │ ├── actions │ │ ├── action-handler-composable.spec.ts │ │ ├── action-handler-composable.ts │ │ ├── action-handler-mixin.spec.ts │ │ ├── action-handler-mixin.ts │ │ ├── action.spec.ts │ │ ├── action.ts │ │ ├── actions-mixin.ts │ │ ├── actions-vuetify.spec.ts │ │ ├── actions-vuetify.vue │ │ ├── filtered-actions.spec.ts │ │ ├── filtered-actions.ts │ │ └── namespace.ts │ ├── adapters │ │ ├── api │ │ │ ├── detail-view-api.spec.ts │ │ │ ├── detail-view-api.ts │ │ │ ├── index.ts │ │ │ ├── namespace.ts │ │ │ ├── view-api.ts │ │ │ ├── view-generic.ts │ │ │ ├── view-set-api.ts │ │ │ └── view-set-generic.ts │ │ ├── index.ts │ │ └── namespace.ts │ ├── api_consumer │ │ ├── Readme.md │ │ ├── api-consumer-loader.vue │ │ ├── api-consumer.spec.json │ │ ├── api-consumer.spec.ts │ │ ├── api-consumer.vue │ │ ├── component-display.ts │ │ ├── consumer-logic-api.ts │ │ ├── consumer-logic-array.spec.json │ │ ├── consumer-logic-array.spec.ts │ │ ├── consumer-logic-array.ts │ │ ├── consumer-logic-base.ts │ │ ├── form-consumer │ │ │ ├── api.spec.json │ │ │ ├── api.spec.ts │ │ │ ├── api.ts │ │ │ ├── array.spec.json │ │ │ ├── array.spec.ts │ │ │ ├── array.ts │ │ │ ├── base.ts │ │ │ ├── index.ts │ │ │ ├── namespace.ts │ │ │ └── one-shot │ │ │ │ ├── api.spec.json │ │ │ │ ├── api.spec.ts │ │ │ │ ├── api.ts │ │ │ │ ├── array.spec.json │ │ │ │ ├── array.spec.ts │ │ │ │ ├── array.ts │ │ │ │ ├── base.ts │ │ │ │ └── index.ts │ │ ├── index-temporary.ts │ │ └── namespace.ts │ ├── classes │ │ ├── display-mode.spec.ts │ │ ├── display-mode.ts │ │ ├── indexed-array.spec.ts │ │ └── indexed-array.ts │ ├── df-app.spec.ts │ ├── df-app.vue │ ├── form │ │ ├── definitions │ │ │ ├── field-operator.spec.ts │ │ │ ├── field-operator.ts │ │ │ ├── field-render-params.spec.ts │ │ │ ├── field-render-params.ts │ │ │ ├── field.spec.ts │ │ │ ├── field.ts │ │ │ ├── form-payload.spec.ts │ │ │ ├── form-payload.ts │ │ │ └── layout.ts │ │ ├── field-group.vue │ │ ├── form-component.vue │ │ ├── form-field.vue │ │ ├── inputs │ │ │ ├── base.ts │ │ │ ├── conditional-visibility.spec.ts │ │ │ ├── conditional-visibility.ts │ │ │ ├── date-time.vue │ │ │ ├── df-checkbox.vue │ │ │ ├── df-ckeditor.vue │ │ │ ├── df-color.vue │ │ │ ├── df-file.vue │ │ │ ├── df-input.vue │ │ │ ├── df-list.vue │ │ │ ├── df-placeholder.vue │ │ │ ├── df-select.vue │ │ │ ├── input-vuetify.vue │ │ │ └── text-area.vue │ │ ├── layout-vuetify.vue │ │ ├── namespace.ts │ │ └── row.vue │ ├── modal │ │ ├── definitions │ │ │ ├── dialog-size.spec.ts │ │ │ └── dialog-size.ts │ │ ├── dialog-definition.spec.ts │ │ ├── dialog-definition.ts │ │ ├── index.ts │ │ ├── modal-api-vuetify.vue │ │ ├── modal-renderer.ts │ │ ├── modal-view-api.spec.ts │ │ ├── modal-view-api.ts │ │ ├── modal-view-list.spec.ts │ │ ├── modal-view-list.ts │ │ ├── modal-view.ts │ │ ├── modal.ts │ │ └── namespace.ts │ ├── notifications │ │ ├── df-notifications.vue │ │ └── index.ts │ ├── table │ │ ├── cell-renderers │ │ │ ├── index.ts │ │ │ ├── table-cell-date-time.vue │ │ │ └── table-cell-float.vue │ │ ├── column-group.vue │ │ ├── definitions │ │ │ ├── column-ordering-direction.spec.ts │ │ │ ├── column-ordering-direction.ts │ │ │ ├── column-ordering.spec.ts │ │ │ ├── column-ordering.ts │ │ │ ├── column.spec.ts │ │ │ ├── column.ts │ │ │ ├── columns.ts │ │ │ ├── filterrow.ts │ │ │ ├── responsive-layout.ts │ │ │ ├── row-types.spec.ts │ │ │ ├── row-types.ts │ │ │ ├── row.spec.ts │ │ │ ├── row.ts │ │ │ ├── rows.spec.ts │ │ │ └── rows.ts │ │ ├── namespace.ts │ │ ├── ordering-indicator.vue │ │ ├── render-measure.ts │ │ ├── rows-visibility-observer.ts │ │ ├── table-style.vue │ │ ├── table-vuetify.vue │ │ ├── table.ts │ │ ├── tbody-generic.vue │ │ ├── tcolumn-generic.vue │ │ ├── thead-generic.vue │ │ └── trow-generic.vue │ ├── util │ │ ├── api-client.ts │ │ ├── get-object-from-path.spec.ts │ │ ├── get-object-from-path.ts │ │ ├── index.ts │ │ ├── internal-record.spec.ts │ │ ├── internal-record.ts │ │ ├── loading-indicator.spec.ts │ │ ├── loading-indicator.vue │ │ ├── request-tracker.spec.ts │ │ ├── request-tracker.ts │ │ ├── translations-mixin.spec.ts │ │ └── translations-mixin.ts │ └── vuetify.ts ├── index.ts ├── vue.d.ts └── vuetify-components.ts ├── tsconfig.build.json ├── tsconfig.json └── vite.config.ts /.actrc: -------------------------------------------------------------------------------- 1 | # sample .actrc file 2 | -P ubuntu-latest=nektos/act-environments-ubuntu:18.04 -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | plugins = 3 | django_coverage_plugin 4 | 5 | source = dynamicforms 6 | 7 | omit = 8 | doc/* 9 | tests/* 10 | setup/wsgi.py 11 | rest_framework/* 12 | 13 | [report] 14 | show_missing = true 15 | precision = 2 16 | -------------------------------------------------------------------------------- /.github/workflows/check_code.yml: -------------------------------------------------------------------------------- 1 | name: Code check 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | lint: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | - uses: chartboost/ruff-action@v1 11 | with: 12 | args: "check --diff" 13 | -------------------------------------------------------------------------------- /.github/workflows/check_doc.yml: -------------------------------------------------------------------------------- 1 | name: Python check documentation 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | strategy: 10 | matrix: 11 | python: [3.9] 12 | 13 | steps: 14 | - uses: actions/checkout@v3 15 | - name: Setup Python 16 | uses: actions/setup-python@v4 17 | with: 18 | python-version: ${{ matrix.python }} 19 | - name: Install Tox and any other packages 20 | run: | 21 | pip install tox 22 | - name: Run Tox 23 | run: tox -e doc 24 | -------------------------------------------------------------------------------- /.github/workflows/vitest_tests.yml: -------------------------------------------------------------------------------- 1 | name: Vitest Tests 2 | on: [push] 3 | 4 | jobs: 5 | build: 6 | runs-on: ubuntu-latest 7 | timeout-minutes: 10 8 | 9 | steps: 10 | - uses: actions/checkout@v3 11 | - name: Use Node.js 12 | uses: actions/setup-node@v3 13 | with: 14 | node-version: '18.13.0' 15 | - name: Install Dependencies 16 | run: npm ci 17 | - name: Test build 18 | run: npm run build-no-tsc --if-present 19 | - name: Run tests 20 | run: npm test 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /DynamicForms.egg-info 2 | *.pyc 3 | *~ 4 | .idea 5 | *.bak 6 | .#* 7 | \#* 8 | *.db 9 | *.tmp 10 | *.mo 11 | .tox 12 | rest_framework 13 | db.sqlite3 14 | /docs/_build/ 15 | /docs/.vitepress/cache/**/* 16 | /geckodriver.log 17 | venv/ 18 | .venv/ 19 | media 20 | /node_modules 21 | /coverage 22 | /dynamicforms/static/ckeditor5/ 23 | /dynamicforms/vue/node_modules/ 24 | /dynamicforms/vue/package-lock.json 25 | /vue/dynamicforms/README.md 26 | /dist/ 27 | setup/env.py 28 | 29 | # Local configuration 30 | .env.local 31 | 32 | # Make sure to add .vitepress/dist and .vitepress/cache to your .gitignore file. 33 | .vitepress/dist 34 | .vitepress/cache 35 | 36 | # Coverage generated files 37 | coverage/ 38 | .coverage 39 | .coverage.json 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright © 2017-present, Jure Erznožnik. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst 2 | include LICENSE.rst 3 | include requirements.txt 4 | include requirements_test_functional.txt 5 | recursive-include dynamicforms * 6 | recursive-include dynamicforms_legacy * 7 | global-exclude __pycache__ 8 | global-exclude *.py[co] 9 | -------------------------------------------------------------------------------- /docs/.docs_archive/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | # sphinx-autobuild -v -n -a . _build\html 4 | 5 | # You can set these variables from the command line. 6 | SPHINXOPTS = 7 | SPHINXBUILD = sphinx-build 8 | SPHINXPROJ = DynamicForms 9 | SOURCEDIR = . 10 | BUILDDIR = _build 11 | 12 | # Put it first so that "make" without argument is like "make help". 13 | help: 14 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 15 | 16 | .PHONY: help Makefile 17 | 18 | # Catch-all target: route all unknown targets to Sphinx using the new 19 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 20 | %: Makefile 21 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /docs/.docs_archive/documents/api/action_controls.rst: -------------------------------------------------------------------------------- 1 | Action controls 2 | =============== 3 | 4 | Class reference 5 | --------------- 6 | 7 | .. automodule:: dynamicforms.action 8 | :members: -------------------------------------------------------------------------------- /docs/.docs_archive/documents/api/context_processors.rst: -------------------------------------------------------------------------------- 1 | Context processors 2 | ================== 3 | 4 | .. automodule:: dynamicforms.context_processors 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/.docs_archive/documents/api/dialogs.rst: -------------------------------------------------------------------------------- 1 | Dialogs 2 | ======= 3 | 4 | Dialogs offer more flexibility by allowing you to place them on screen when needed instead of having them pre-rendered 5 | in the page. Their contents are always fresh and theirHTML adapts to the task at hand. For example, when user makes a 6 | mistake entering data, the returned dialog will already contain all the warnings in the HTML. 7 | 8 | To use, either add `?df_render_type=dialog` to URL or add a `X_DF_RENDER_TYPE=dialog` HTTP header to request. 9 | 10 | The default dialog templates allow for some customisation of dialog rendered. 11 | 12 | Dialog classes 13 | -------------- 14 | 15 | .. code-block:: python 16 | 17 | class MyViewSet(viewsets.ModelViewSet): 18 | template_context = dict(url_reverse='my-item', dialog_classes='dialog-lg') 19 | 20 | Good for specifying additional dialog classes, like how large the dialog should be. 21 | 22 | Dialog header classes 23 | --------------------- 24 | 25 | .. code-block:: python 26 | 27 | class MyViewSet(viewsets.ModelViewSet): 28 | template_context = dict(url_reverse='my-item', dialog_header_classes='bg-info') 29 | 30 | Good for specifying additional dialog header classes, like typeof dialog (warning, info, primary, etc) 31 | 32 | -------------------------------------------------------------------------------- /docs/.docs_archive/documents/api/fields.rst: -------------------------------------------------------------------------------- 1 | Fields 2 | ====== 3 | 4 | Re-declares all DRF fields such that they also inherit DynamicForms' mixins. 5 | 6 | To use, import like so: 7 | 8 | .. code-block:: python 9 | 10 | from dynamicforms.fields import {your desired field classes} 11 | 12 | Make sure you don't import DRF's field classes over these. 13 | 14 | 15 | Class reference 16 | --------------- 17 | 18 | .. automodule:: dynamicforms.fields 19 | :members: 20 | :undoc-members: 21 | 22 | 23 | Field mixins 24 | ------------ 25 | 26 | .. automodule:: dynamicforms.mixins 27 | :members: 28 | -------------------------------------------------------------------------------- /docs/.docs_archive/documents/api/index.rst: -------------------------------------------------------------------------------- 1 | DynamicForms API reference 2 | ========================== 3 | 4 | 5 | .. toctree:: 6 | 7 | action_controls 8 | context_processors 9 | dialogs 10 | fields 11 | renderers 12 | serializers 13 | templatetags 14 | viewsets 15 | -------------------------------------------------------------------------------- /docs/.docs_archive/documents/api/renderers.rst: -------------------------------------------------------------------------------- 1 | Renderers 2 | ========= 3 | 4 | Contains template renderers. 5 | 6 | To use, declare renderers in settings.py, like so: 7 | 8 | .. code-block:: python 9 | 10 | REST_FRAMEWORK = { 11 | 'DEFAULT_RENDERER_CLASSES': ( 12 | 'rest_framework.renderers.JSONRenderer', 13 | 'rest_framework.renderers.BrowsableAPIRenderer', 14 | 'dynamicforms.renderers.TemplateHTMLRenderer', 15 | ) 16 | } 17 | 18 | 19 | Class reference 20 | --------------- 21 | 22 | .. automodule:: dynamicforms.renderers 23 | :members: 24 | -------------------------------------------------------------------------------- /docs/.docs_archive/documents/api/serializers.rst: -------------------------------------------------------------------------------- 1 | Serializers 2 | =========== 3 | 4 | Currently only provides ModelSerializer for model-based data manipulation. 5 | 6 | To use, import like so: 7 | 8 | .. code-block:: python 9 | 10 | from dynamicforms.serializers import ModelSerializer 11 | 12 | Make sure you don't import DRF's ModelSerializer over this one. 13 | 14 | Class reference 15 | --------------- 16 | 17 | .. autoclass:: dynamicforms.serializers.ModelSerializer 18 | :members: 19 | -------------------------------------------------------------------------------- /docs/.docs_archive/documents/api/templatetags.rst: -------------------------------------------------------------------------------- 1 | Template tags 2 | ============= 3 | 4 | Tag reference 5 | ------------- 6 | 7 | .. automodule:: dynamicforms.templatetags.dynamicforms 8 | :members: get_data_template, render_field,render_form,set_var,set_var_conditional, 9 | render_table_commands, table_columns_count 10 | 11 | Filter reference 12 | ---------------- 13 | 14 | .. automodule:: dynamicforms.templatetags.dynamicforms 15 | :members: 16 | :exclude-members: get_data_template, render_field,render_form,set_var,set_var_conditional, 17 | render_table_commands, table_columns_count 18 | :noindex: 19 | -------------------------------------------------------------------------------- /docs/.docs_archive/documents/api/viewsets.rst: -------------------------------------------------------------------------------- 1 | ViewSets 2 | ======== 3 | 4 | Currently only provides ModelViewSet for model-based data manipulation. 5 | 6 | To use, import like so: 7 | 8 | .. code-block:: python 9 | 10 | from dynamicforms.viewsets import ModelViewSet 11 | 12 | Make sure you don't import DRF's ModelViewSet over this one. 13 | 14 | Class reference 15 | --------------- 16 | 17 | .. autoclass:: dynamicforms.viewsets.ModelViewSet 18 | :members: template_context, get_queryset, filter_queryset, filter_queryset_field, generate_paged_loader 19 | :exclude-members: initialize_request 20 | 21 | .. automethod:: new_object 22 | -------------------------------------------------------------------------------- /docs/.docs_archive/documents/guides/index.rst: -------------------------------------------------------------------------------- 1 | Using DynamicForms 2 | ================== 3 | 4 | .. toctree:: 5 | 6 | Quick start 7 | templates 8 | 9 | .. todo:: Custom page template 10 | .. todo:: Custom dialog classes for dialog formatting 11 | .. todo:: SingleRecordViewSet 12 | .. todo:: RenderMixin - parameters and what they do 13 | -------------------------------------------------------------------------------- /docs/.docs_archive/index.rst: -------------------------------------------------------------------------------- 1 | .. DynamicForms documentation master file, created by 2 | sphinx-quickstart on Fri Aug 31 12:25:37 2018. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to DynamicForms's documentation! 7 | ======================================== 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | About 14 | Guides 15 | Configuration 16 | API reference 17 | Contributor's documentation 18 | 19 | Indices and tables 20 | ================== 21 | 22 | * :ref:`genindex` 23 | * :ref:`modindex` 24 | * :ref:`search` 25 | -------------------------------------------------------------------------------- /docs/.docs_archive/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | set SPHINXPROJ=DynamicForms 13 | 14 | if "%1" == "" goto help 15 | if "%1" == "autobuild" goto autobuild 16 | 17 | %SPHINXBUILD% >NUL 2>NUL 18 | if errorlevel 9009 ( 19 | echo. 20 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 21 | echo.installed, then set the SPHINXBUILD environment variable to point 22 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 23 | echo.may add the Sphinx directory to PATH. 24 | echo. 25 | echo.If you don't have Sphinx installed, grab it from 26 | echo.http://sphinx-doc.org/ 27 | exit /b 1 28 | ) 29 | 30 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 31 | goto end 32 | 33 | :help 34 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 35 | goto end 36 | 37 | :autobuild 38 | sphinx-autobuild -v -n -a . _build\html 39 | goto end 40 | 41 | :end 42 | popd 43 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | // https://vitepress.dev/guide/custom-theme 2 | import { h } from 'vue' 3 | import type { Theme } from 'vitepress' 4 | import DefaultTheme from 'vitepress/theme' 5 | import './style.css' 6 | 7 | export default { 8 | extends: DefaultTheme, 9 | Layout: () => { 10 | return h(DefaultTheme.Layout, null, { 11 | // https://vitepress.dev/guide/extending-default-theme#layout-slots 12 | }) 13 | }, 14 | enhanceApp({ app, router, siteData }) { 15 | // ... 16 | } 17 | } satisfies Theme 18 | -------------------------------------------------------------------------------- /docs/examples/api-examples.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # Runtime API Examples 6 | 7 | This page demonstrates usage of some of the runtime APIs provided by VitePress. 8 | 9 | The main `useData()` API can be used to access site, theme, and page data for the current page. It works in both `.md` and `.vue` files: 10 | 11 | ```md 12 | 17 | 18 | ## Results 19 | 20 | ### Theme Data 21 |
{{ theme }}
22 | 23 | ### Page Data 24 |
{{ page }}
25 | 26 | ### Page Frontmatter 27 |
{{ frontmatter }}
28 | ``` 29 | 30 | 35 | 36 | ## Results 37 | 38 | ### Theme Data 39 |
{{ theme }}
40 | 41 | ### Page Data 42 |
{{ page }}
43 | 44 | ### Page Frontmatter 45 |
{{ frontmatter }}
46 | 47 | ## More 48 | 49 | Check out the documentation for the [full list of runtime APIs](https://vitepress.dev/reference/runtime-api#usedata). 50 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | # https://vitepress.dev/reference/default-theme-home-page 3 | layout: home 4 | title: DynamicForms 5 | titleTemplate: Django DRF REST to HTML forms, tables and dialogs 6 | 7 | hero: 8 | name: "DynamicForms" 9 | text: "Developers handbook" 10 | tagline: Django DRF REST to HTML forms, tables and dialogs 11 | actions: 12 | - theme: alt 13 | text: Getting started 14 | link: /getting-started 15 | - theme: alt 16 | text: Settings 17 | link: /settings 18 | # - theme: brand 19 | # text: Markdown Examples 20 | # link: /markdown-examples 21 | # - theme: alt 22 | # text: API Examples 23 | # link: /api-examples 24 | 25 | features: 26 | - title: HTML forms 27 | details: Turn your rest-framework ViewSets into HTML forms 28 | - title: Powerful HTML based CRUD 29 | details: Support for fetching “new” records, both in JSON or in HTML... 30 | - title: Clear separation of list & dialog templates 31 | details: Custom templates whenever & wherever you want them. 32 | --- 33 | 34 | -------------------------------------------------------------------------------- /docs/reference/hiding_titlebar_and_navbar.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # Hiding Titlebar and Navbar 6 | 7 | When embedding forms or data pages into other pages, or making the data full-screen, you may wish to hide the navigation 8 | elements from the view. This is done with route meta data with the following settings: 9 | 10 | - `fullscreen: true` - hides all navigation elements 11 | - `hideTitlebar: true` - hides just the Titlebar 12 | - `hideNavbar: true` - hides just the navigation bar 13 | 14 | For any of the above, just a true value is strict-checked. If it is anything but `true`, the setting is off. 15 | 16 | example: 17 | 18 | ```ts 19 | const routes = [ 20 | ... 21 | { 22 | name: 'Consumer Form', 23 | path: '/form-consumer', 24 | component: FormConsumer, 25 | meta: { title: 'Consumer Form', fullscreen: true }, 26 | }, 27 | ... 28 | ] 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/reference/index.md: -------------------------------------------------------------------------------- 1 | # DynamicForms reference 2 | 3 | This is the reference manual for DynamicForms. 4 | -------------------------------------------------------------------------------- /dynamicforms/__init__.py: -------------------------------------------------------------------------------- 1 | __title__ = "DynamicForms" 2 | __version__ = '0.77.35' 3 | __author__ = "Jure Erznožnik" 4 | __email__ = "jure.erznoznik@gmail.com" 5 | __license__ = "BSD 3-Clause" 6 | __copyright__ = "Copyright 2017-present Jure Erznožnik" 7 | 8 | VERSION = __version__ 9 | -------------------------------------------------------------------------------- /dynamicforms/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms/migrations/__init__.py -------------------------------------------------------------------------------- /dynamicforms/mixins/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | import abc 3 | 4 | from rest_framework.fields import Field as DRFField 5 | 6 | from .action import ActionMixin 7 | from .choice import ChoiceMixin 8 | from .color_field import ColorFieldMixin 9 | from .conditional_visibility import ConditionalVisibilityMixin, F, FieldType, S, Statement 10 | from .enable_copy import EnableCopyMixin 11 | from .field_render import DisplayMode, FieldAlignment, FieldRenderMixin 12 | from .file_field import FileFieldMixin 13 | from .help_text import FieldHelpTextMixin 14 | from .implicit_hidden import HiddenFieldMixin 15 | from .implicit_natural_date import DateFieldMixin, DateTimeFieldMixin, TimeFieldMixin 16 | from .null_value import NullValueMixin 17 | from .password_field import PasswordFieldMixin 18 | from .related_field_ajax import RelatedFieldAJAXMixin 19 | from .rtf_field import RTFFieldMixin 20 | 21 | 22 | class DFField(FieldRenderMixin, ActionMixin, FieldHelpTextMixin, ConditionalVisibilityMixin, DRFField, abc.ABC): 23 | """ 24 | Class only for type hinting 25 | """ 26 | 27 | pass 28 | -------------------------------------------------------------------------------- /dynamicforms/mixins/action.py: -------------------------------------------------------------------------------- 1 | from dynamicforms.action import Actions 2 | 3 | 4 | class ActionMixin(object): 5 | """ 6 | Used in fields allowing declaration of actions that happen when field values change 7 | """ 8 | 9 | def __init__(self, *args, actions: Actions = None, **kwargs): 10 | super().__init__(*args, **kwargs) 11 | act = actions or Actions(None) 12 | act.actions.extend(getattr(self, "actions", Actions()).actions) 13 | # Obtain a personalised list of actions 14 | self.actions = act.get_resolved_copy(self) 15 | -------------------------------------------------------------------------------- /dynamicforms/mixins/choice/null_choice.py: -------------------------------------------------------------------------------- 1 | from rest_framework.fields import ChoiceField 2 | 3 | 4 | class NullChoiceMixin(object): 5 | """ 6 | Declaring ChoiceField's null_choice_text 7 | (what should be rendered for "no selection"; DRF's default is ---------) 8 | We also support user declaring a choice with None value and a different text (see hidden fields example) 9 | """ 10 | 11 | @property 12 | def null_choice_text(self): 13 | res = "--------" 14 | if isinstance(self, ChoiceField) and not getattr(self, "get_queryset", None): 15 | # Only do this for true ChoiceFields. RelatedFields would run a query here 16 | # Possibly we will at some point have to enable this for relatedfields too 17 | for opt in self.iter_options(): 18 | if opt.start_option_group or opt.end_option_group: 19 | pass 20 | elif opt.value is None: 21 | res = opt.display_text 22 | return res 23 | 24 | def iter_options_bound(self, value): 25 | # noinspection PyUnresolvedReferences 26 | return super().iter_options() 27 | -------------------------------------------------------------------------------- /dynamicforms/mixins/choice/single_choice.py: -------------------------------------------------------------------------------- 1 | from ..field_render import DisplayMode 2 | 3 | 4 | class SingleChoiceMixin: 5 | def __init__(self, *args, single_choice_hide=False, **kwargs): 6 | super().__init__(*args, **kwargs) 7 | self.single_choice_hide = single_choice_hide 8 | 9 | def to_internal_value(self, data): 10 | if self.single_choice_hide and len(self.choices) == 1: 11 | data = list(self.choices)[0] 12 | elif self.single_choice_hide and len(self.choices) < 1: 13 | data = None 14 | return super().to_internal_value(data) 15 | 16 | def set_single_choice_hide(self, value): 17 | self._single_choice_hide = value 18 | if value and len(self.choices) <= 1: 19 | self.display_form = DisplayMode.HIDDEN 20 | 21 | single_choice_hide = property(lambda self: self._single_choice_hide, set_single_choice_hide) 22 | -------------------------------------------------------------------------------- /dynamicforms/mixins/color_field.py: -------------------------------------------------------------------------------- 1 | class ColorFieldMixin(object): 2 | def __init__(self, *args, **kwargs): 3 | super().__init__(*args, **kwargs) 4 | self.render_params["form_component_name"] = "DColor" 5 | -------------------------------------------------------------------------------- /dynamicforms/mixins/enable_copy.py: -------------------------------------------------------------------------------- 1 | class EnableCopyMixin(object): 2 | def __init__(self, *args, enable_copy=False, **kwargs): 3 | super().__init__(*args, **kwargs) 4 | self.enable_copy = enable_copy or False 5 | -------------------------------------------------------------------------------- /dynamicforms/mixins/implicit_hidden.py: -------------------------------------------------------------------------------- 1 | from .field_render import DisplayMode, FieldRenderMixin 2 | 3 | 4 | class HiddenFieldMixin(FieldRenderMixin): 5 | def __init__(self, *args, **kwargs): 6 | kwargs.setdefault("display_table", DisplayMode.SUPPRESS) 7 | super().__init__(*args, **kwargs) 8 | -------------------------------------------------------------------------------- /dynamicforms/mixins/null_value.py: -------------------------------------------------------------------------------- 1 | from rest_framework.fields import IntegerField 2 | 3 | 4 | class NullValueMixin(object): 5 | def to_internal_value(self, data): 6 | if data == "" and self.allow_null: 7 | self.validators = [] 8 | return None 9 | return super().to_internal_value(data) 10 | 11 | def to_representation(self, value, row_data=None): 12 | if value is None and self.allow_null and not isinstance(self, IntegerField): 13 | value = "" 14 | 15 | return super().to_representation(value, row_data) 16 | -------------------------------------------------------------------------------- /dynamicforms/mixins/password_field.py: -------------------------------------------------------------------------------- 1 | class PasswordFieldMixin(object): 2 | def __init__(self, *args, password_field=False, **kwargs): 3 | super().__init__(*args, **kwargs) 4 | self.password_field = password_field 5 | 6 | def set_password_field(self, value): 7 | from dynamicforms.mixins import DisplayMode 8 | 9 | self._password_field = value 10 | if value: 11 | self.display_table = DisplayMode.SUPPRESS 12 | self.style.update(input_type="password") 13 | self.render_params["form_component_name"] = "DInput" 14 | self.render_params["input_type"] = "password" 15 | else: 16 | try: 17 | self.style["input_type"] 18 | self.style.update(input_type="text") 19 | self.display_table = DisplayMode.FULL 20 | except: 21 | pass 22 | 23 | password_field = property(lambda self: self._password_field, set_password_field) 24 | -------------------------------------------------------------------------------- /dynamicforms/models.py: -------------------------------------------------------------------------------- 1 | # supposedly required so that tests & stuff works 2 | 3 | # from django.db import models 4 | 5 | # Create your models here. 6 | -------------------------------------------------------------------------------- /dynamicforms/renderers.py: -------------------------------------------------------------------------------- 1 | from .template_render import ComponentDefRenderer # noqa: F401 2 | -------------------------------------------------------------------------------- /dynamicforms/template_render/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | What DynamicForms is about: ability to render a Serializer directly in Django template --> HTML 3 | This module allows for it. It defines __str__ method on Serializer, ListSerializer and Field instances to render to HTML 4 | """ 5 | from .mixins.field import ViewModeField 6 | from .mixins.listserializer import ViewModeListSerializer 7 | from .mixins.serializer import ViewModeSerializer 8 | from .renderer import ComponentDefRenderer 9 | 10 | __all__ = (ViewModeField, ViewModeSerializer, ViewModeListSerializer, ComponentDefRenderer) 11 | -------------------------------------------------------------------------------- /dynamicforms/template_render/mixins/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms/template_render/mixins/__init__.py -------------------------------------------------------------------------------- /dynamicforms/template_render/mixins/base.py: -------------------------------------------------------------------------------- 1 | from dynamicforms.fields import DFField 2 | 3 | from .render_mode_enum import ViewModeEnum 4 | 5 | 6 | class ViewModeBase(object): 7 | view_mode = None 8 | 9 | def set_view_mode(self, view_mode: "ViewModeEnum"): 10 | self.view_mode = view_mode 11 | 12 | def set_bound_value(self, *args): 13 | """ 14 | Used to set the bound value. However, implementation is class-specific, so we only declare this so that 15 | implementations are checked to contain the method 16 | """ 17 | raise NotImplementedError() 18 | 19 | def render(self: "_ViewModeBoundField"): 20 | view_mode_name = f"render_{self.view_mode.name.lower()}" 21 | render_func = getattr(self, view_mode_name, None) 22 | if render_func is None: 23 | raise NotImplementedError( 24 | f'ViewMode object {self.__class__.__name__}{(" " + self.label) if self.label else ""} has view_mode ' 25 | f"set to {self.view_mode.name}, but doesn't handle rendering for it" 26 | ) 27 | return render_func() 28 | 29 | def __str__(self): 30 | return self.render() 31 | 32 | 33 | # noinspection PyAbstractClass 34 | class _ViewModeBoundField(ViewModeBase, DFField): 35 | """ 36 | Dummy class just for type hinting 37 | """ 38 | 39 | pass 40 | -------------------------------------------------------------------------------- /dynamicforms/template_render/mixins/render_mode_enum.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class ViewModeEnum(Enum): 5 | # noinspection PyMethodParameters 6 | def _generate_next_value_(name, start, count, last_values): 7 | # We use this construct to obtain value same as name 8 | return name 9 | -------------------------------------------------------------------------------- /dynamicforms/template_render/mixins/serializer_filter.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from typing import Optional, TYPE_CHECKING 4 | 5 | if TYPE_CHECKING: 6 | from dynamicforms.serializers import DynamicFormsSerializer 7 | 8 | 9 | class SerializerFilter(object): 10 | def get_filter_serializer(self) -> Optional["DynamicFormsSerializer"]: 11 | return self.filter_data if not self.is_filter else None 12 | 13 | def filter_serializer_component_params(self) -> Optional[dict]: 14 | filter_serializer: Optional["DynamicFormsSerializer"] = self.get_filter_serializer() 15 | params: Optional[dict] = json.loads(filter_serializer.component_params()) if filter_serializer else None 16 | if not params: 17 | return None 18 | params["uuid"] = self.uuid 19 | return params 20 | -------------------------------------------------------------------------------- /dynamicforms/template_render/mixins/serializer_render_actions.py: -------------------------------------------------------------------------------- 1 | """ 2 | Class that contains renderable fields for the templates. 3 | The class provides transformation functionality 4 | """ 5 | 6 | from typing import Iterable 7 | 8 | from dynamicforms.action import TableAction 9 | 10 | 11 | class SerializerRenderActions(object): 12 | @property 13 | def actions(self) -> Iterable[TableAction]: 14 | raise NotImplementedError("You must implement the actions property in your serializer render_actions method") 15 | 16 | def as_action_def(self): 17 | res = {action.name: action.as_component_def() for action in self.actions} 18 | return res 19 | 20 | def __aiter__(self): 21 | return self.actions 22 | -------------------------------------------------------------------------------- /dynamicforms/template_render/mixins/util.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from rest_framework.utils.encoders import JSONEncoder 4 | 5 | 6 | def convert_to_json_if(data, output_json: bool = True): 7 | if output_json: 8 | return json.dumps(data, cls=JSONEncoder) 9 | return data 10 | -------------------------------------------------------------------------------- /dynamicforms/template_render/renderer.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Optional 2 | 3 | from rest_framework.renderers import JSONRenderer 4 | from rest_framework.utils.serializer_helpers import ReturnDict, ReturnList 5 | 6 | 7 | def data_is_paginated(data): 8 | return ( 9 | isinstance(data, dict) 10 | and "next" in data 11 | and "results" in data 12 | and isinstance(data["results"], (ReturnList, ReturnDict)) 13 | ) 14 | 15 | 16 | def get_serializer(data) -> Optional[Any]: 17 | if data_is_paginated(data): 18 | return data["results"].serializer 19 | if isinstance(data, (ReturnList, ReturnDict)): 20 | return data.serializer 21 | return None 22 | 23 | 24 | class ComponentDefRenderer(JSONRenderer): 25 | format = "componentdef" 26 | 27 | def render(self, data, accepted_media_type=None, renderer_context=None): 28 | serializer = get_serializer(data) 29 | 30 | if serializer is None and isinstance(data, dict) and "detail" in data: 31 | return super().render(data, accepted_media_type, renderer_context) 32 | 33 | assert serializer is not None 34 | 35 | serializer.apply_component_context() 36 | component_params = serializer.component_params(output_json=False) 37 | 38 | return super().render(component_params, accepted_media_type, renderer_context) 39 | -------------------------------------------------------------------------------- /dynamicforms/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import re_path 2 | 3 | from dynamicforms import preupload_files, progress 4 | 5 | urlpatterns = [ 6 | # Progress is used for checking on progress of operation on server 7 | re_path(r"^progress/$", progress.get_progress_value, name="progress"), 8 | re_path(r"^preupload-file/(?P[\w-]+/)?$", preupload_files.FileUploadView.as_view(), name="preupload-file"), 9 | ] 10 | -------------------------------------------------------------------------------- /dynamicforms/utils.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import traceback 3 | 4 | from typing import Union 5 | 6 | from django.db.models import Model, QuerySet 7 | from rest_framework.utils.model_meta import get_field_info 8 | 9 | 10 | def get_pk_name(obj: Union[Model, QuerySet]): 11 | if isinstance(obj, QuerySet): 12 | return get_field_info(obj.model).pk.name 13 | return get_field_info(obj).pk.name 14 | 15 | def print_field_declaration_line(): 16 | """ 17 | This method prints the line where the field has been declared 18 | Must be called from field __init__ 19 | """ 20 | print("WARNING: This field should be converted to AJAX.", file=sys.stderr) 21 | # Iterate over the stack in reverse to find the first occurrence of "Serializer" 22 | stack = traceback.extract_stack() 23 | end_index = len(stack) 24 | for i, frame in enumerate(stack, 0): 25 | if "Serializer" in frame.name or "Serializer" in frame.line: 26 | end_index = i 27 | for frame in stack[end_index:end_index + 1]: 28 | print( 29 | f'File "{frame.filename}", line {frame.lineno}, in {frame.name}\n {frame.line.strip()}', 30 | file=sys.stderr 31 | ) 32 | 33 | -------------------------------------------------------------------------------- /dynamicforms/views.py: -------------------------------------------------------------------------------- 1 | # from django.shortcuts import render 2 | -------------------------------------------------------------------------------- /dynamicforms_dev/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_dev/__init__.py -------------------------------------------------------------------------------- /dynamicforms_dev/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_dev/management/__init__.py -------------------------------------------------------------------------------- /dynamicforms_dev/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_dev/management/commands/__init__.py -------------------------------------------------------------------------------- /dynamicforms_dev/management/commands/npm_run.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os 3 | import subprocess 4 | 5 | from django.core.management.base import BaseCommand 6 | 7 | 8 | class Command(BaseCommand): 9 | help = "Generate Field classes from DRF with applied DynamicForms mixins" 10 | 11 | def add_arguments(self, parser: argparse.ArgumentParser): 12 | parser.add_argument( 13 | "command", 14 | type=str, 15 | default="serve", 16 | action="store", 17 | nargs="?", 18 | help='command to run, e.g. "build" or "serve". default: "serve"', 19 | ) 20 | parser.add_argument("cmd_params", nargs=argparse.REMAINDER) 21 | 22 | def handle(self, *args, **options): 23 | cmd = options.get("command") 24 | pth = os.path.abspath(os.path.join(os.path.split(__file__)[0], "..", "..", "..")) 25 | pth = os.path.join(pth, "dynamicforms", "vue") 26 | print(["npm", "run", cmd] + options.get("cmd_params")) 27 | p = subprocess.Popen(["npm", "run", cmd] + options.get("cmd_params"), cwd=pth) 28 | p.wait() 29 | -------------------------------------------------------------------------------- /dynamicforms_legacy/__init__.py: -------------------------------------------------------------------------------- 1 | __title__ = "DynamicForms" 2 | __version__ = "0.50.1" 3 | __author__ = "Jure Erznožnik" 4 | __email__ = "jure.erznoznik@gmail.com" 5 | __license__ = "BSD 3-Clause" 6 | __copyright__ = "Copyright 2017-present Jure Erznožnik" 7 | 8 | VERSION = __version__ 9 | -------------------------------------------------------------------------------- /dynamicforms_legacy/context_processors.py: -------------------------------------------------------------------------------- 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 `_ 25 | :return: dict with `DYNAMICFORMS` context variable set 26 | """ 27 | return dict(DYNAMICFORMS=DYNAMICFORMS) 28 | -------------------------------------------------------------------------------- /dynamicforms_legacy/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/migrations/__init__.py -------------------------------------------------------------------------------- /dynamicforms_legacy/mixins/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | 3 | from .action import ActionMixin 4 | from .allow_tags import AllowTagsMixin 5 | from .enable_copy import EnableCopyMixin 6 | from .file_field import FileFieldMixin 7 | from .help_text import FieldHelpTextMixin 8 | from .implicit_hidden import HiddenFieldMixin 9 | from .implicit_natural_date import DateFieldMixin, DateTimeFieldMixin, TimeFieldMixin 10 | from .null_choice import NullChoiceMixin 11 | from .null_value import NullValueMixin 12 | from .password_field import PasswordFieldMixin 13 | from .related_field_ajax import RelatedFieldAJAXMixin 14 | from .render import DisplayMode, RenderMixin 15 | from .rtf_field import RTFFieldMixin 16 | from .single_choice import SingleChoiceMixin 17 | -------------------------------------------------------------------------------- /dynamicforms_legacy/mixins/action.py: -------------------------------------------------------------------------------- 1 | from dynamicforms_legacy.action import Actions 2 | 3 | 4 | class ActionMixin(object): 5 | """ 6 | Used in fields allowing declaration of actions that happen when field values change 7 | """ 8 | 9 | def __init__(self, *args, actions: Actions = None, **kwargs): 10 | super().__init__(*args, **kwargs) 11 | act = actions or Actions(None) 12 | act.actions.extend(getattr(self, "actions", Actions()).actions) 13 | # Obtain a personalised list of actions 14 | self.actions = act.get_resolved_copy(self) 15 | -------------------------------------------------------------------------------- /dynamicforms_legacy/mixins/enable_copy.py: -------------------------------------------------------------------------------- 1 | class EnableCopyMixin(object): 2 | def __init__(self, *args, enable_copy=False, **kwargs): 3 | super().__init__(*args, **kwargs) 4 | self.enable_copy = enable_copy or False 5 | -------------------------------------------------------------------------------- /dynamicforms_legacy/mixins/file_field.py: -------------------------------------------------------------------------------- 1 | class FileFieldMixin(object): 2 | def __init__(self, **kwargs) -> None: 3 | super().__init__(**kwargs) 4 | # noinspection PyUnresolvedReferences 5 | self.style.setdefault("no_filter", True) 6 | -------------------------------------------------------------------------------- /dynamicforms_legacy/mixins/implicit_hidden.py: -------------------------------------------------------------------------------- 1 | from .render import DisplayMode, RenderMixin 2 | 3 | 4 | class HiddenFieldMixin(RenderMixin): 5 | def __init__(self, *args, **kwargs): 6 | kwargs.setdefault("display_table", DisplayMode.SUPPRESS) 7 | super().__init__(*args, **kwargs) 8 | -------------------------------------------------------------------------------- /dynamicforms_legacy/mixins/null_choice.py: -------------------------------------------------------------------------------- 1 | from rest_framework.fields import ChoiceField 2 | 3 | 4 | class NullChoiceMixin(object): 5 | """ 6 | Declaring ChoiceField's null_choice_text 7 | (what should be rendered for "no selection"; DRF's default is ---------) 8 | We also support user declaring a choice with None value and a different text (see hidden fields example) 9 | """ 10 | 11 | @property 12 | def null_choice_text(self): 13 | res = "--------" 14 | if isinstance(self, ChoiceField) and not getattr(self, "get_queryset", None): 15 | # Only do this for true ChoiceFields. RelatedFields would run a query here 16 | # Possibly we will at some point have to enable this for relatedfields too 17 | for opt in self.iter_options(): 18 | if opt.start_option_group or opt.end_option_group: 19 | pass 20 | elif opt.value is None: 21 | res = opt.display_text 22 | return res 23 | 24 | def iter_options_bound(self, value): 25 | # noinspection PyUnresolvedReferences 26 | return super().iter_options() 27 | -------------------------------------------------------------------------------- /dynamicforms_legacy/mixins/null_value.py: -------------------------------------------------------------------------------- 1 | from rest_framework.fields import IntegerField 2 | 3 | 4 | class NullValueMixin(object): 5 | def to_internal_value(self, data): 6 | if data == "" and self.allow_null: 7 | self.validators = [] 8 | return None 9 | return super().to_internal_value(data) 10 | 11 | def to_representation(self, value, row_data=None): 12 | if value is None and self.allow_null and not isinstance(self, IntegerField): 13 | value = "" 14 | 15 | return super().to_representation(value, row_data) 16 | -------------------------------------------------------------------------------- /dynamicforms_legacy/mixins/password_field.py: -------------------------------------------------------------------------------- 1 | class PasswordFieldMixin(object): 2 | def __init__(self, *args, password_field=False, **kwargs): 3 | super().__init__(*args, **kwargs) 4 | self.password_field = password_field 5 | 6 | def set_password_field(self, value): 7 | self._password_field = value 8 | if value: 9 | self.display_table = "DisplayMode.SUPRESS" 10 | self.style.update(input_type="password") 11 | else: 12 | try: 13 | self.style["input_type"] 14 | self.style.update(input_type="text") 15 | self.display_table = "DisplayMode.FULL" 16 | except: 17 | pass 18 | 19 | password_field = property(lambda self: self._password_field, set_password_field) 20 | -------------------------------------------------------------------------------- /dynamicforms_legacy/mixins/single_choice.py: -------------------------------------------------------------------------------- 1 | from .render import DisplayMode 2 | 3 | 4 | class SingleChoiceMixin: 5 | def __init__(self, *args, single_choice_hide=False, **kwargs): 6 | super().__init__(*args, **kwargs) 7 | self.single_choice_hide = single_choice_hide 8 | 9 | def to_internal_value(self, data): 10 | if self.single_choice_hide and len(self.choices) == 1: 11 | data = list(self.choices)[0] 12 | elif self.single_choice_hide and len(self.choices) < 1: 13 | data = None 14 | return super().to_internal_value(data) 15 | 16 | def set_single_choice_hide(self, value): 17 | self._single_choice_hide = value 18 | if value and len(self.choices) <= 1: 19 | self.display_form = DisplayMode.HIDDEN 20 | 21 | single_choice_hide = property(lambda self: self._single_choice_hide, set_single_choice_hide) 22 | -------------------------------------------------------------------------------- /dynamicforms_legacy/models.py: -------------------------------------------------------------------------------- 1 | # supposedly required so that tests & stuff works 2 | 3 | # from django.db import models 4 | 5 | # Create your models here. 6 | -------------------------------------------------------------------------------- /dynamicforms_legacy/static/bootstrap-3.4.1-dist/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/static/bootstrap-3.4.1-dist/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /dynamicforms_legacy/static/bootstrap-3.4.1-dist/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/static/bootstrap-3.4.1-dist/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /dynamicforms_legacy/static/bootstrap-3.4.1-dist/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/static/bootstrap-3.4.1-dist/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /dynamicforms_legacy/static/bootstrap-3.4.1-dist/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/static/bootstrap-3.4.1-dist/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /dynamicforms_legacy/static/bootstrap-3.4.1-dist/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /dynamicforms_legacy/static/dynamicforms/icons/copy.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | -------------------------------------------------------------------------------- /dynamicforms_legacy/static/dynamicforms/icons/eye-off-outline.svg: -------------------------------------------------------------------------------- 1 | 2 | ionicons-v5-i 3 | 4 | 6 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /dynamicforms_legacy/static/dynamicforms/icons/eye-outline.svg: -------------------------------------------------------------------------------- 1 | 2 | ionicons-v5-i 3 | 6 | 7 | -------------------------------------------------------------------------------- /dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png -------------------------------------------------------------------------------- /dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_diagonals-thick_20_666666_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_diagonals-thick_20_666666_40x40.png -------------------------------------------------------------------------------- /dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_glass_100_f6f6f6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_glass_100_f6f6f6_1x400.png -------------------------------------------------------------------------------- /dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_glass_100_fdf5ce_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_glass_100_fdf5ce_1x400.png -------------------------------------------------------------------------------- /dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png -------------------------------------------------------------------------------- /dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png -------------------------------------------------------------------------------- /dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png -------------------------------------------------------------------------------- /dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_228ef1_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_228ef1_256x240.png -------------------------------------------------------------------------------- /dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_ef8c08_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_ef8c08_256x240.png -------------------------------------------------------------------------------- /dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_ffd27a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_ffd27a_256x240.png -------------------------------------------------------------------------------- /dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_ffffff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_ffffff_256x240.png -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/af.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/af",[],function(){return{errorLoading:function(){return"Die resultate kon nie gelaai word nie."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Verwyders asseblief "+t+" character";return t!=1&&(n+="s"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Voer asseblief "+t+" of meer karakters";return n},loadingMore:function(){return"Meer resultate word gelaai…"},maximumSelected:function(e){var t="Kies asseblief net "+e.maximum+" item";return e.maximum!=1&&(t+="s"),t},noResults:function(){return"Geen resultate gevind"},searching:function(){return"Besig…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ar.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ar",[],function(){return{errorLoading:function(){return"لا يمكن تحميل النتائج"},inputTooLong:function(e){var t=e.input.length-e.maximum;return"الرجاء حذف "+t+" عناصر"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"الرجاء إضافة "+t+" عناصر"},loadingMore:function(){return"جاري تحميل نتائج إضافية..."},maximumSelected:function(e){return"تستطيع إختيار "+e.maximum+" بنود فقط"},noResults:function(){return"لم يتم العثور على أي نتائج"},searching:function(){return"جاري البحث…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/az.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/az",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum;return t+" simvol silin"},inputTooShort:function(e){var t=e.minimum-e.input.length;return t+" simvol daxil edin"},loadingMore:function(){return"Daha çox nəticə yüklənir…"},maximumSelected:function(e){return"Sadəcə "+e.maximum+" element seçə bilərsiniz"},noResults:function(){return"Nəticə tapılmadı"},searching:function(){return"Axtarılır…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/bg.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/bg",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Моля въведете с "+t+" по-малко символ";return t>1&&(n+="a"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Моля въведете още "+t+" символ";return t>1&&(n+="a"),n},loadingMore:function(){return"Зареждат се още…"},maximumSelected:function(e){var t="Можете да направите до "+e.maximum+" ";return e.maximum>1?t+="избора":t+="избор",t},noResults:function(){return"Няма намерени съвпадения"},searching:function(){return"Търсене…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/bs.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/bs",[],function(){function e(e,t,n,r){return e%10==1&&e%100!=11?t:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?n:r}return{errorLoading:function(){return"Preuzimanje nije uspijelo."},inputTooLong:function(t){var n=t.input.length-t.maximum,r="Obrišite "+n+" simbol";return r+=e(n,"","a","a"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Ukucajte bar još "+n+" simbol";return r+=e(n,"","a","a"),r},loadingMore:function(){return"Preuzimanje još rezultata…"},maximumSelected:function(t){var n="Možete izabrati samo "+t.maximum+" stavk";return n+=e(t.maximum,"u","e","i"),n},noResults:function(){return"Ništa nije pronađeno"},searching:function(){return"Pretraga…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ca.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ca",[],function(){return{errorLoading:function(){return"La càrrega ha fallat"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Si us plau, elimina "+t+" car";return t==1?n+="àcter":n+="àcters",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Si us plau, introdueix "+t+" car";return t==1?n+="àcter":n+="àcters",n},loadingMore:function(){return"Carregant més resultats…"},maximumSelected:function(e){var t="Només es pot seleccionar "+e.maximum+" element";return e.maximum!=1&&(t+="s"),t},noResults:function(){return"No s'han trobat resultats"},searching:function(){return"Cercant…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/cs.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/cs",[],function(){function e(e,t){switch(e){case 2:return t?"dva":"dvě";case 3:return"tři";case 4:return"čtyři"}return""}return{errorLoading:function(){return"Výsledky nemohly být načteny."},inputTooLong:function(t){var n=t.input.length-t.maximum;return n==1?"Prosím, zadejte o jeden znak méně.":n<=4?"Prosím, zadejte o "+e(n,!0)+" znaky méně.":"Prosím, zadejte o "+n+" znaků méně."},inputTooShort:function(t){var n=t.minimum-t.input.length;return n==1?"Prosím, zadejte ještě jeden znak.":n<=4?"Prosím, zadejte ještě další "+e(n,!0)+" znaky.":"Prosím, zadejte ještě dalších "+n+" znaků."},loadingMore:function(){return"Načítají se další výsledky…"},maximumSelected:function(t){var n=t.maximum;return n==1?"Můžete zvolit jen jednu položku.":n<=4?"Můžete zvolit maximálně "+e(n,!1)+" položky.":"Můžete zvolit maximálně "+n+" položek."},noResults:function(){return"Nenalezeny žádné položky."},searching:function(){return"Vyhledávání…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/da.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/da",[],function(){return{errorLoading:function(){return"Resultaterne kunne ikke indlæses."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Angiv venligst "+t+" tegn mindre"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Angiv venligst "+t+" tegn mere"},loadingMore:function(){return"Indlæser flere resultater…"},maximumSelected:function(e){var t="Du kan kun vælge "+e.maximum+" emne";return e.maximum!=1&&(t+="r"),t},noResults:function(){return"Ingen resultater fundet"},searching:function(){return"Søger…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/de.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/de",[],function(){return{errorLoading:function(){return"Die Ergebnisse konnten nicht geladen werden."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Bitte "+t+" Zeichen weniger eingeben"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Bitte "+t+" Zeichen mehr eingeben"},loadingMore:function(){return"Lade mehr Ergebnisse…"},maximumSelected:function(e){var t="Sie können nur "+e.maximum+" Eintr";return e.maximum===1?t+="ag":t+="äge",t+=" auswählen",t},noResults:function(){return"Keine Übereinstimmungen gefunden"},searching:function(){return"Suche…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/dsb.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/dsb",[],function(){var e=["znamuško","znamušce","znamuška","znamuškow"],t=["zapisk","zapiska","zapiski","zapiskow"],n=function(t,n){if(t===1)return n[0];if(t===2)return n[1];if(t>2&&t<=4)return n[2];if(t>=5)return n[3]};return{errorLoading:function(){return"Wuslědki njejsu se dali zacytaś."},inputTooLong:function(t){var r=t.input.length-t.maximum;return"Pšosym lašuj "+r+" "+n(r,e)},inputTooShort:function(t){var r=t.minimum-t.input.length;return"Pšosym zapódaj nanejmjenjej "+r+" "+n(r,e)},loadingMore:function(){return"Dalšne wuslědki se zacytaju…"},maximumSelected:function(e){return"Móžoš jano "+e.maximum+" "+n(e.maximum,t)+"wubraś."},noResults:function(){return"Žedne wuslědki namakane"},searching:function(){return"Pyta se…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/el.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/el",[],function(){return{errorLoading:function(){return"Τα αποτελέσματα δεν μπόρεσαν να φορτώσουν."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Παρακαλώ διαγράψτε "+t+" χαρακτήρ";return t==1&&(n+="α"),t!=1&&(n+="ες"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Παρακαλώ συμπληρώστε "+t+" ή περισσότερους χαρακτήρες";return n},loadingMore:function(){return"Φόρτωση περισσότερων αποτελεσμάτων…"},maximumSelected:function(e){var t="Μπορείτε να επιλέξετε μόνο "+e.maximum+" επιλογ";return e.maximum==1&&(t+="ή"),e.maximum!=1&&(t+="ές"),t},noResults:function(){return"Δεν βρέθηκαν αποτελέσματα"},searching:function(){return"Αναζήτηση…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/en.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/en",[],function(){return{errorLoading:function(){return"The results could not be loaded."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Please delete "+t+" character";return t!=1&&(n+="s"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Please enter "+t+" or more characters";return n},loadingMore:function(){return"Loading more results…"},maximumSelected:function(e){var t="You can only select "+e.maximum+" item";return e.maximum!=1&&(t+="s"),t},noResults:function(){return"No results found"},searching:function(){return"Searching…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/es.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/es",[],function(){return{errorLoading:function(){return"No se pudieron cargar los resultados"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Por favor, elimine "+t+" car";return t==1?n+="ácter":n+="acteres",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Por favor, introduzca "+t+" car";return t==1?n+="ácter":n+="acteres",n},loadingMore:function(){return"Cargando más resultados…"},maximumSelected:function(e){var t="Sólo puede seleccionar "+e.maximum+" elemento";return e.maximum!=1&&(t+="s"),t},noResults:function(){return"No se encontraron resultados"},searching:function(){return"Buscando…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/et.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/et",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Sisesta "+t+" täht";return t!=1&&(n+="e"),n+=" vähem",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Sisesta "+t+" täht";return t!=1&&(n+="e"),n+=" rohkem",n},loadingMore:function(){return"Laen tulemusi…"},maximumSelected:function(e){var t="Saad vaid "+e.maximum+" tulemus";return e.maximum==1?t+="e":t+="t",t+=" valida",t},noResults:function(){return"Tulemused puuduvad"},searching:function(){return"Otsin…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/eu.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/eu",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Idatzi ";return t==1?n+="karaktere bat":n+=t+" karaktere",n+=" gutxiago",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Idatzi ";return t==1?n+="karaktere bat":n+=t+" karaktere",n+=" gehiago",n},loadingMore:function(){return"Emaitza gehiago kargatzen…"},maximumSelected:function(e){return e.maximum===1?"Elementu bakarra hauta dezakezu":e.maximum+" elementu hauta ditzakezu soilik"},noResults:function(){return"Ez da bat datorrenik aurkitu"},searching:function(){return"Bilatzen…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/fa.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/fa",[],function(){return{errorLoading:function(){return"امکان بارگذاری نتایج وجود ندارد."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="لطفاً "+t+" کاراکتر را حذف نمایید";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="لطفاً تعداد "+t+" کاراکتر یا بیشتر وارد نمایید";return n},loadingMore:function(){return"در حال بارگذاری نتایج بیشتر..."},maximumSelected:function(e){var t="شما تنها می‌توانید "+e.maximum+" آیتم را انتخاب نمایید";return t},noResults:function(){return"هیچ نتیجه‌ای یافت نشد"},searching:function(){return"در حال جستجو..."}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/fi.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/fi",[],function(){return{errorLoading:function(){return"Tuloksia ei saatu ladattua."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Ole hyvä ja anna "+t+" merkkiä vähemmän"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Ole hyvä ja anna "+t+" merkkiä lisää"},loadingMore:function(){return"Ladataan lisää tuloksia…"},maximumSelected:function(e){return"Voit valita ainoastaan "+e.maximum+" kpl"},noResults:function(){return"Ei tuloksia"},searching:function(){return"Haetaan…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/fr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/fr",[],function(){return{errorLoading:function(){return"Les résultats ne peuvent pas être chargés."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Supprimez "+t+" caractère"+(t>1)?"s":""},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Saisissez au moins "+t+" caractère"+(t>1)?"s":""},loadingMore:function(){return"Chargement de résultats supplémentaires…"},maximumSelected:function(e){return"Vous pouvez seulement sélectionner "+e.maximum+" élément"+(e.maximum>1)?"s":""},noResults:function(){return"Aucun résultat trouvé"},searching:function(){return"Recherche en cours…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/gl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/gl",[],function(){return{errorLoading:function(){return"Non foi posíbel cargar os resultados."},inputTooLong:function(e){var t=e.input.length-e.maximum;return t===1?"Elimine un carácter":"Elimine "+t+" caracteres"},inputTooShort:function(e){var t=e.minimum-e.input.length;return t===1?"Engada un carácter":"Engada "+t+" caracteres"},loadingMore:function(){return"Cargando máis resultados…"},maximumSelected:function(e){return e.maximum===1?"Só pode seleccionar un elemento":"Só pode seleccionar "+e.maximum+" elementos"},noResults:function(){return"Non se atoparon resultados"},searching:function(){return"Buscando…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/he.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/he",[],function(){return{errorLoading:function(){return"שגיאה בטעינת התוצאות"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="נא למחוק ";return t===1?n+="תו אחד":n+=t+" תווים",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="נא להכניס ";return t===1?n+="תו אחד":n+=t+" תווים",n+=" או יותר",n},loadingMore:function(){return"טוען תוצאות נוספות…"},maximumSelected:function(e){var t="באפשרותך לבחור עד ";return e.maximum===1?t+="פריט אחד":t+=e.maximum+" פריטים",t},noResults:function(){return"לא נמצאו תוצאות"},searching:function(){return"מחפש…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/hi.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/hi",[],function(){return{errorLoading:function(){return"परिणामों को लोड नहीं किया जा सका।"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+" अक्षर को हटा दें";return t>1&&(n=t+" अक्षरों को हटा दें "),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="कृपया "+t+" या अधिक अक्षर दर्ज करें";return n},loadingMore:function(){return"अधिक परिणाम लोड हो रहे है..."},maximumSelected:function(e){var t="आप केवल "+e.maximum+" आइटम का चयन कर सकते हैं";return t},noResults:function(){return"कोई परिणाम नहीं मिला"},searching:function(){return"खोज रहा है..."}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/hr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/hr",[],function(){function e(e){var t=" "+e+" znak";return e%10<5&&e%10>0&&(e%100<5||e%100>19)?e%10>1&&(t+="a"):t+="ova",t}return{errorLoading:function(){return"Preuzimanje nije uspjelo."},inputTooLong:function(t){var n=t.input.length-t.maximum;return"Unesite "+e(n)},inputTooShort:function(t){var n=t.minimum-t.input.length;return"Unesite još "+e(n)},loadingMore:function(){return"Učitavanje rezultata…"},maximumSelected:function(e){return"Maksimalan broj odabranih stavki je "+e.maximum},noResults:function(){return"Nema rezultata"},searching:function(){return"Pretraga…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/hsb.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/hsb",[],function(){var e=["znamješko","znamješce","znamješka","znamješkow"],t=["zapisk","zapiskaj","zapiski","zapiskow"],n=function(t,n){if(t===1)return n[0];if(t===2)return n[1];if(t>2&&t<=4)return n[2];if(t>=5)return n[3]};return{errorLoading:function(){return"Wuslědki njedachu so začitać."},inputTooLong:function(t){var r=t.input.length-t.maximum;return"Prošu zhašej "+r+" "+n(r,e)},inputTooShort:function(t){var r=t.minimum-t.input.length;return"Prošu zapodaj znajmjeńša "+r+" "+n(r,e)},loadingMore:function(){return"Dalše wuslědki so začitaja…"},maximumSelected:function(e){return"Móžeš jenož "+e.maximum+" "+n(e.maximum,t)+"wubrać"},noResults:function(){return"Žane wuslědki namakane"},searching:function(){return"Pyta so…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/hu.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/hu",[],function(){return{errorLoading:function(){return"Az eredmények betöltése nem sikerült."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Túl hosszú. "+t+" karakterrel több, mint kellene."},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Túl rövid. Még "+t+" karakter hiányzik."},loadingMore:function(){return"Töltés…"},maximumSelected:function(e){return"Csak "+e.maximum+" elemet lehet kiválasztani."},noResults:function(){return"Nincs találat."},searching:function(){return"Keresés…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/hy.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/hy",[],function(){return{errorLoading:function(){return"Արդյունքները հնարավոր չէ բեռնել։"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Խնդրում ենք հեռացնել "+t+" նշան";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Խնդրում ենք մուտքագրել "+t+" կամ ավել նշաններ";return n},loadingMore:function(){return"Բեռնվում են նոր արդյունքներ․․․"},maximumSelected:function(e){var t="Դուք կարող եք ընտրել առավելագույնը "+e.maximum+" կետ";return t},noResults:function(){return"Արդյունքներ չեն գտնվել"},searching:function(){return"Որոնում․․․"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/id.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/id",[],function(){return{errorLoading:function(){return"Data tidak boleh diambil."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Hapuskan "+t+" huruf"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Masukkan "+t+" huruf lagi"},loadingMore:function(){return"Mengambil data…"},maximumSelected:function(e){return"Anda hanya dapat memilih "+e.maximum+" pilihan"},noResults:function(){return"Tidak ada data yang sesuai"},searching:function(){return"Mencari…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/is.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/is",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vinsamlegast styttið texta um "+t+" staf";return t<=1?n:n+"i"},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vinsamlegast skrifið "+t+" staf";return t>1&&(n+="i"),n+=" í viðbót",n},loadingMore:function(){return"Sæki fleiri niðurstöður…"},maximumSelected:function(e){return"Þú getur aðeins valið "+e.maximum+" atriði"},noResults:function(){return"Ekkert fannst"},searching:function(){return"Leita…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/it.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/it",[],function(){return{errorLoading:function(){return"I risultati non possono essere caricati."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Per favore cancella "+t+" caratter";return t!==1?n+="i":n+="e",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Per favore inserisci "+t+" o più caratteri";return n},loadingMore:function(){return"Caricando più risultati…"},maximumSelected:function(e){var t="Puoi selezionare solo "+e.maximum+" element";return e.maximum!==1?t+="i":t+="o",t},noResults:function(){return"Nessun risultato trovato"},searching:function(){return"Sto cercando…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ja.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ja",[],function(){return{errorLoading:function(){return"結果が読み込まれませんでした"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+" 文字を削除してください";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="少なくとも "+t+" 文字を入力してください";return n},loadingMore:function(){return"読み込み中…"},maximumSelected:function(e){var t=e.maximum+" 件しか選択できません";return t},noResults:function(){return"対象が見つかりません"},searching:function(){return"検索しています…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/km.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/km",[],function(){return{errorLoading:function(){return"មិនអាចទាញយកទិន្នន័យ"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="សូមលុបចេញ "+t+" អក្សរ";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="សូមបញ្ចូល"+t+" អក្សរ រឺ ច្រើនជាងនេះ";return n},loadingMore:function(){return"កំពុងទាញយកទិន្នន័យបន្ថែម..."},maximumSelected:function(e){var t="អ្នកអាចជ្រើសរើសបានតែ "+e.maximum+" ជម្រើសប៉ុណ្ណោះ";return t},noResults:function(){return"មិនមានលទ្ធផល"},searching:function(){return"កំពុងស្វែងរក..."}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ko.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ko",[],function(){return{errorLoading:function(){return"결과를 불러올 수 없습니다."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="너무 깁니다. "+t+" 글자 지워주세요.";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="너무 짧습니다. "+t+" 글자 더 입력해주세요.";return n},loadingMore:function(){return"불러오는 중…"},maximumSelected:function(e){var t="최대 "+e.maximum+"개까지만 선택 가능합니다.";return t},noResults:function(){return"결과가 없습니다."},searching:function(){return"검색 중…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/lt.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/lt",[],function(){function e(e,t,n,r){return e%10===1&&(e%100<11||e%100>19)?t:e%10>=2&&e%10<=9&&(e%100<11||e%100>19)?n:r}return{inputTooLong:function(t){var n=t.input.length-t.maximum,r="Pašalinkite "+n+" simbol";return r+=e(n,"į","ius","ių"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Įrašykite dar "+n+" simbol";return r+=e(n,"į","ius","ių"),r},loadingMore:function(){return"Kraunama daugiau rezultatų…"},maximumSelected:function(t){var n="Jūs galite pasirinkti tik "+t.maximum+" element";return n+=e(t.maximum,"ą","us","ų"),n},noResults:function(){return"Atitikmenų nerasta"},searching:function(){return"Ieškoma…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/lv.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/lv",[],function(){function e(e,t,n,r){return e===11?t:e%10===1?n:r}return{inputTooLong:function(t){var n=t.input.length-t.maximum,r="Lūdzu ievadiet par "+n;return r+=" simbol"+e(n,"iem","u","iem"),r+" mazāk"},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Lūdzu ievadiet vēl "+n;return r+=" simbol"+e(n,"us","u","us"),r},loadingMore:function(){return"Datu ielāde…"},maximumSelected:function(t){var n="Jūs varat izvēlēties ne vairāk kā "+t.maximum;return n+=" element"+e(t.maximum,"us","u","us"),n},noResults:function(){return"Sakritību nav"},searching:function(){return"Meklēšana…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/mk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/mk",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Ве молиме внесете "+e.maximum+" помалку карактер";return e.maximum!==1&&(n+="и"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Ве молиме внесете уште "+e.maximum+" карактер";return e.maximum!==1&&(n+="и"),n},loadingMore:function(){return"Вчитување резултати…"},maximumSelected:function(e){var t="Можете да изберете само "+e.maximum+" ставк";return e.maximum===1?t+="а":t+="и",t},noResults:function(){return"Нема пронајдено совпаѓања"},searching:function(){return"Пребарување…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ms.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ms",[],function(){return{errorLoading:function(){return"Keputusan tidak berjaya dimuatkan."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Sila hapuskan "+t+" aksara"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Sila masukkan "+t+" atau lebih aksara"},loadingMore:function(){return"Sedang memuatkan keputusan…"},maximumSelected:function(e){return"Anda hanya boleh memilih "+e.maximum+" pilihan"},noResults:function(){return"Tiada padanan yang ditemui"},searching:function(){return"Mencari…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/nb.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/nb",[],function(){return{errorLoading:function(){return"Kunne ikke hente resultater."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Vennligst fjern "+t+" tegn"},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vennligst skriv inn "+t+" tegn til";return n+" tegn til"},loadingMore:function(){return"Laster flere resultater…"},maximumSelected:function(e){return"Du kan velge maks "+e.maximum+" elementer"},noResults:function(){return"Ingen treff"},searching:function(){return"Søker…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/nl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/nl",[],function(){return{errorLoading:function(){return"De resultaten konden niet worden geladen."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Gelieve "+t+" karakters te verwijderen";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Gelieve "+t+" of meer karakters in te voeren";return n},loadingMore:function(){return"Meer resultaten laden…"},maximumSelected:function(e){var t=e.maximum==1?"kan":"kunnen",n="Er "+t+" maar "+e.maximum+" item";return e.maximum!=1&&(n+="s"),n+=" worden geselecteerd",n},noResults:function(){return"Geen resultaten gevonden…"},searching:function(){return"Zoeken…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/pl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/pl",[],function(){var e=["znak","znaki","znaków"],t=["element","elementy","elementów"],n=function(t,n){if(t===1)return n[0];if(t>1&&t<=4)return n[1];if(t>=5)return n[2]};return{errorLoading:function(){return"Nie można załadować wyników."},inputTooLong:function(t){var r=t.input.length-t.maximum;return"Usuń "+r+" "+n(r,e)},inputTooShort:function(t){var r=t.minimum-t.input.length;return"Podaj przynajmniej "+r+" "+n(r,e)},loadingMore:function(){return"Trwa ładowanie…"},maximumSelected:function(e){return"Możesz zaznaczyć tylko "+e.maximum+" "+n(e.maximum,t)},noResults:function(){return"Brak wyników"},searching:function(){return"Trwa wyszukiwanie…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ps.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ps",[],function(){return{errorLoading:function(){return"پايلي نه سي ترلاسه کېدای"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="د مهربانۍ لمخي "+t+" توری ړنګ کړئ";return t!=1&&(n=n.replace("توری","توري")),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="لږ تر لږه "+t+" يا ډېر توري وليکئ";return n},loadingMore:function(){return"نوري پايلي ترلاسه کيږي..."},maximumSelected:function(e){var t="تاسو يوازي "+e.maximum+" قلم په نښه کولای سی";return e.maximum!=1&&(t=t.replace("قلم","قلمونه")),t},noResults:function(){return"پايلي و نه موندل سوې"},searching:function(){return"لټول کيږي..."}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/pt-BR.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/pt-BR",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Apague "+t+" caracter";return t!=1&&(n+="es"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Digite "+t+" ou mais caracteres";return n},loadingMore:function(){return"Carregando mais resultados…"},maximumSelected:function(e){var t="Você só pode selecionar "+e.maximum+" ite";return e.maximum==1?t+="m":t+="ns",t},noResults:function(){return"Nenhum resultado encontrado"},searching:function(){return"Buscando…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/pt.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/pt",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Por favor apague "+t+" ";return n+=t!=1?"caracteres":"caractere",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Introduza "+t+" ou mais caracteres";return n},loadingMore:function(){return"A carregar mais resultados…"},maximumSelected:function(e){var t="Apenas pode seleccionar "+e.maximum+" ";return t+=e.maximum!=1?"itens":"item",t},noResults:function(){return"Sem resultados"},searching:function(){return"A procurar…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ro.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ro",[],function(){return{errorLoading:function(){return"Rezultatele nu au putut fi incărcate."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vă rugăm să ștergeți"+t+" caracter";return t!==1&&(n+="e"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vă rugăm să introduceți "+t+" sau mai multe caractere";return n},loadingMore:function(){return"Se încarcă mai multe rezultate…"},maximumSelected:function(e){var t="Aveți voie să selectați cel mult "+e.maximum;return t+=" element",e.maximum!==1&&(t+="e"),t},noResults:function(){return"Nu au fost găsite rezultate"},searching:function(){return"Căutare…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ru.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ru",[],function(){function e(e,t,n,r){return e%10<5&&e%10>0&&e%100<5||e%100>20?e%10>1?n:t:r}return{errorLoading:function(){return"Невозможно загрузить результаты"},inputTooLong:function(t){var n=t.input.length-t.maximum,r="Пожалуйста, введите на "+n+" символ";return r+=e(n,"","a","ов"),r+=" меньше",r},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Пожалуйста, введите еще хотя бы "+n+" символ";return r+=e(n,"","a","ов"),r},loadingMore:function(){return"Загрузка данных…"},maximumSelected:function(t){var n="Вы можете выбрать не более "+t.maximum+" элемент";return n+=e(t.maximum,"","a","ов"),n},noResults:function(){return"Совпадений не найдено"},searching:function(){return"Поиск…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/sk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/sk",[],function(){var e={2:function(e){return e?"dva":"dve"},3:function(){return"tri"},4:function(){return"štyri"}};return{errorLoading:function(){return"Výsledky sa nepodarilo načítať."},inputTooLong:function(t){var n=t.input.length-t.maximum;return n==1?"Prosím, zadajte o jeden znak menej":n>=2&&n<=4?"Prosím, zadajte o "+e[n](!0)+" znaky menej":"Prosím, zadajte o "+n+" znakov menej"},inputTooShort:function(t){var n=t.minimum-t.input.length;return n==1?"Prosím, zadajte ešte jeden znak":n<=4?"Prosím, zadajte ešte ďalšie "+e[n](!0)+" znaky":"Prosím, zadajte ešte ďalších "+n+" znakov"},loadingMore:function(){return"Načítanie ďalších výsledkov…"},maximumSelected:function(t){return t.maximum==1?"Môžete zvoliť len jednu položku":t.maximum>=2&&t.maximum<=4?"Môžete zvoliť najviac "+e[t.maximum](!1)+" položky":"Môžete zvoliť najviac "+t.maximum+" položiek"},noResults:function(){return"Nenašli sa žiadne položky"},searching:function(){return"Vyhľadávanie…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/sl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/sl",[],function(){return{errorLoading:function(){return"Zadetkov iskanja ni bilo mogoče naložiti."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Prosim zbrišite "+t+" znak";return t==2?n+="a":t!=1&&(n+="e"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Prosim vpišite še "+t+" znak";return t==2?n+="a":t!=1&&(n+="e"),n},loadingMore:function(){return"Nalagam več zadetkov…"},maximumSelected:function(e){var t="Označite lahko največ "+e.maximum+" predmet";return e.maximum==2?t+="a":e.maximum!=1&&(t+="e"),t},noResults:function(){return"Ni zadetkov."},searching:function(){return"Iščem…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/sr-Cyrl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/sr-Cyrl",[],function(){function e(e,t,n,r){return e%10==1&&e%100!=11?t:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?n:r}return{errorLoading:function(){return"Преузимање није успело."},inputTooLong:function(t){var n=t.input.length-t.maximum,r="Обришите "+n+" симбол";return r+=e(n,"","а","а"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Укуцајте бар још "+n+" симбол";return r+=e(n,"","а","а"),r},loadingMore:function(){return"Преузимање још резултата…"},maximumSelected:function(t){var n="Можете изабрати само "+t.maximum+" ставк";return n+=e(t.maximum,"у","е","и"),n},noResults:function(){return"Ништа није пронађено"},searching:function(){return"Претрага…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/sr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/sr",[],function(){function e(e,t,n,r){return e%10==1&&e%100!=11?t:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?n:r}return{errorLoading:function(){return"Preuzimanje nije uspelo."},inputTooLong:function(t){var n=t.input.length-t.maximum,r="Obrišite "+n+" simbol";return r+=e(n,"","a","a"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Ukucajte bar još "+n+" simbol";return r+=e(n,"","a","a"),r},loadingMore:function(){return"Preuzimanje još rezultata…"},maximumSelected:function(t){var n="Možete izabrati samo "+t.maximum+" stavk";return n+=e(t.maximum,"u","e","i"),n},noResults:function(){return"Ništa nije pronađeno"},searching:function(){return"Pretraga…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/sv.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/sv",[],function(){return{errorLoading:function(){return"Resultat kunde inte laddas."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vänligen sudda ut "+t+" tecken";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vänligen skriv in "+t+" eller fler tecken";return n},loadingMore:function(){return"Laddar fler resultat…"},maximumSelected:function(e){var t="Du kan max välja "+e.maximum+" element";return t},noResults:function(){return"Inga träffar"},searching:function(){return"Söker…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/th.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/th",[],function(){return{errorLoading:function(){return"ไม่สามารถค้นข้อมูลได้"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="โปรดลบออก "+t+" ตัวอักษร";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="โปรดพิมพ์เพิ่มอีก "+t+" ตัวอักษร";return n},loadingMore:function(){return"กำลังค้นข้อมูลเพิ่ม…"},maximumSelected:function(e){var t="คุณสามารถเลือกได้ไม่เกิน "+e.maximum+" รายการ";return t},noResults:function(){return"ไม่พบข้อมูล"},searching:function(){return"กำลังค้นข้อมูล…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/tr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/tr",[],function(){return{errorLoading:function(){return"Sonuç yüklenemedi"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+" karakter daha girmelisiniz";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="En az "+t+" karakter daha girmelisiniz";return n},loadingMore:function(){return"Daha fazla…"},maximumSelected:function(e){var t="Sadece "+e.maximum+" seçim yapabilirsiniz";return t},noResults:function(){return"Sonuç bulunamadı"},searching:function(){return"Aranıyor…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/uk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/uk",[],function(){function e(e,t,n,r){return e%100>10&&e%100<15?r:e%10===1?t:e%10>1&&e%10<5?n:r}return{errorLoading:function(){return"Неможливо завантажити результати"},inputTooLong:function(t){var n=t.input.length-t.maximum;return"Будь ласка, видаліть "+n+" "+e(t.maximum,"літеру","літери","літер")},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Будь ласка, введіть "+t+" або більше літер"},loadingMore:function(){return"Завантаження інших результатів…"},maximumSelected:function(t){return"Ви можете вибрати лише "+t.maximum+" "+e(t.maximum,"пункт","пункти","пунктів")},noResults:function(){return"Нічого не знайдено"},searching:function(){return"Пошук…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/vi.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/vi",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vui lòng nhập ít hơn "+t+" ký tự";return t!=1&&(n+="s"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vui lòng nhập nhiều hơn "+t+" ký tự";return n},loadingMore:function(){return"Đang lấy thêm kết quả…"},maximumSelected:function(e){var t="Chỉ có thể chọn được "+e.maximum+" lựa chọn";return t},noResults:function(){return"Không tìm thấy kết quả"},searching:function(){return"Đang tìm…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/zh-CN.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/zh-CN",[],function(){return{errorLoading:function(){return"无法载入结果。"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="请删除"+t+"个字符";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="请再输入至少"+t+"个字符";return n},loadingMore:function(){return"载入更多结果…"},maximumSelected:function(e){var t="最多只能选择"+e.maximum+"个项目";return t},noResults:function(){return"未找到结果"},searching:function(){return"搜索中…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/zh-TW.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/zh-TW",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="請刪掉"+t+"個字元";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="請再輸入"+t+"個字元";return n},loadingMore:function(){return"載入中…"},maximumSelected:function(e){var t="你只能選擇最多"+e.maximum+"項";return t},noResults:function(){return"沒有找到相符的項目"},searching:function(){return"搜尋中…"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% include DYNAMICFORMS.page_includes %} 6 | {% block title %}{% endblock %} 7 | {% block head_extra %}{% endblock %} 8 | 9 | 10 | {% block body %}{% endblock %} 11 | 12 | 13 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/base_includes_select2.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | {% if DYNAMICFORMS.select2_add_include %} 4 | 5 | {% endif %} 6 | 7 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/base_form.html: -------------------------------------------------------------------------------- 1 | {% load dynamicforms %} 2 | {#This template is extended by dynamicforms/base_form#} 3 | 4 | {% block body %} 5 | {% block form_body %}{% endblock %} 6 | {% endblock %} 7 | {% block buttons %} 8 |
  {% block form_buttons %}{% endblock %} 9 |
10 | {% endblock %} 11 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/base_list.html: -------------------------------------------------------------------------------- 1 | {% load dynamicforms %} 2 | {#This template is extended by dynamicforms/base_list#} 3 | 4 | {% block table_class %} 5 | table table-striped 6 | {% endblock %} 7 | {% block th_definition %} 8 | class="{{ table_classes }} {{ ordering }} {% if invisible %}d-none{% endif %}" 9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/base_table_body.html: -------------------------------------------------------------------------------- 1 | {% load dynamicforms %} 2 | {#This template is included by dynamicforms/base_table_body#} 3 | 4 | class="{{ table_classes }}{% if invisible %} d-none{% endif %}" 5 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/base_table_filter.html: -------------------------------------------------------------------------------- 1 | {#This template is included by dynamicforms/base_table_filter#} 2 | 3 | {% if invisible %}class="d-none" 4 | {% elif no_filter %}style="visibility: hidden" 5 | {% endif %} 6 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/field/base_field_v3.html: -------------------------------------------------------------------------------- 1 | {% block class_invisible %} 2 | hidden 3 | {% endblock %} 4 | 5 | {% block class_span_error %} 6 | help-block 7 | {% endblock %} 8 | 9 | {% block class_span_help %} 10 | help-block 11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/field/base_field_v4.html: -------------------------------------------------------------------------------- 1 | {% block class_invisible %} 2 | d-none 3 | {% endblock %} 4 | 5 | {% block class_span_error %} 6 | invalid-feedback 7 | {% endblock %} 8 | 9 | {% block class_span_help %} 10 | form-text text-muted 11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/field/checkbox.html: -------------------------------------------------------------------------------- 1 | {% block input_class %} 2 | "form-check-input{% if not field.label %} position-static{% endif %}" 3 | {% endblock %} 4 | 5 | {% block label_class %} 6 | "form-check-label {% if style.hide_label %}sr-only{% endif %}" 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/field/checkbox_multiple.html: -------------------------------------------------------------------------------- 1 | {% block input_class %} 2 | "form-check-input" 3 | {% endblock %} 4 | 5 | {% block label_class %} 6 | "form-check-label" 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/field/fieldset.html: -------------------------------------------------------------------------------- 1 | {% load dynamicforms %} 2 | 3 | {% field_to_serializer_and_data field %} 4 | {% get_data_template as data_template %} 5 | 6 |
7 |
8 | {{ field.label }} 9 |
10 |
11 | {% if field.errors %} 12 | {% for error in field.errors %} 13 | 14 | {{ error }} 15 | 16 | {% endfor %} 17 | {% endif %} 18 | 19 | {% include data_template with form=serializer %} 20 |
21 |
22 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/field/form.html: -------------------------------------------------------------------------------- 1 | {#This template is included by dynamicforms/field/form.html#} 2 | {% block error_panel %} 3 |
{% block error_data %}{% endblock %}
4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/field/input.html: -------------------------------------------------------------------------------- 1 | {#This template is included by dynamicforms/field/input.html#} 2 | {% block div_password_class %} 3 | input-group 4 | {% endblock %} 5 | 6 | {% block input_class %} 7 | {% if input_type != "file" %}form-control{% else %} form-control-file{% endif %}{% if errors %} is-invalid{% endif %} 8 | {% endblock %} 9 | 10 | {% block password_toggle %} 11 | {% load dynamicforms %} 12 | {% if DYNAMICFORMS.bootstrap_version == 'v4' %} 13 |
14 | {% extendtemplate template_name_var=base_template block="password_span" password_span_visible=True %} 15 |
16 | {% elif DYNAMICFORMS.bootstrap_version == 'v3' %} 17 | 19 | {% extendtemplate template_name_var=base_template block="password_span" password_span_visible=True %} 20 | 21 | {% endif %} 22 | {% endblock %} 23 | 24 | {% block password_span_class %} 25 | {% if DYNAMICFORMS.bootstrap_version == 'v4' %} 26 | input-group-text password-field 27 | {% elif DYNAMICFORMS.bootstrap_version == 'v3' %} 28 | glyphicon glyphicon-eye-open 29 | {% endif %} 30 | 31 | {% endblock %} 32 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/field/list_fieldset.html: -------------------------------------------------------------------------------- 1 | {% load dynamicforms %} 2 | 3 | {% field_to_serializer_and_data field %} 4 | {% get_data_template as data_template %} 5 | 6 |
7 |
8 | {{ field.label }} 9 | {% render_table_commands field.child 'header' %} 10 |
11 |
12 | {% include data_template with serializer=serializer data=data %} 13 | 14 | 17 |
18 |
19 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/field/radio.html: -------------------------------------------------------------------------------- 1 | {#This template is included by dynamicforms/field/radio.html#} 2 | {% block input_class %} 3 | form-check-input 4 | {% endblock %} 5 | 6 | {% block label_class %} 7 | form-check-label 8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/field/rtf_field.html: -------------------------------------------------------------------------------- 1 | {#This template is included by dynamicforms/field/rtf_field.html#} 2 | {% block field_class %} 3 | form-control {% if errors %}is-invalid{% endif %} 4 | {% endblock %} -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/field/select_multiple.html: -------------------------------------------------------------------------------- 1 | {% block select_class %} 2 | form-control {% if errors %}is-invalid{% endif %} 3 | {% endblock %} 4 | 5 | {% block select_style %} 6 | width: 100%; 7 | {% endblock %} 8 | 9 | {% block script_use_select_2 %} 10 | {% if DYNAMICFORMS.use_select2 %} 11 | {% block script_use_select_2_body %}{% endblock %} 12 | {% endif %} 13 | {% endblock %} 14 | 15 | {% block select2_additional_conf %} 16 | , theme: '{{ DYNAMICFORMS.select2_theme }}' 17 | {% endblock %} 18 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/field/textarea.html: -------------------------------------------------------------------------------- 1 | {#This template is included by dynamicforms/field/textarea.html#} 2 | {% block field_class %} 3 | form-control {% if errors %}is-invalid{% endif %} 4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/modal_dialog.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 14 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/modal_dialog_rest.html: -------------------------------------------------------------------------------- 1 | {% load dynamicforms %} 2 | {#This template is extended by dynamicforms/modal_dialog_rest#} 3 | 4 | 24 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/bootstrap/page.html: -------------------------------------------------------------------------------- 1 | {#This template is extended by dynamicforms/page#} 2 | {% load dynamicforms %} 3 |
4 |
5 | {% block title_header %}{% endblock %} 6 | {% block render_table_commands %}{% endblock %} 7 |
8 |
9 | {% block page_body %}{% endblock %} 10 |
11 |
12 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/field/checkbox.html: -------------------------------------------------------------------------------- 1 | {% extends DYNAMICFORMS.field_base_template %} 2 | {% load dynamicforms %} 3 | 4 | {% block container_definition %} 5 | {% with 'checkbox' as input_type %} 6 | {{ block.super }} 7 | {% endwith %} 8 | {% endblock %} 9 | 10 | {% block field_input_label %} 11 | {% set_var templatename=DYNAMICFORMS.template|add:'field/checkbox.html' %} 12 | 13 | 21 | {% if field.label %} 22 | 27 | {% endif %} 28 | {% endblock %} 29 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/field/checkbox_multiple.html: -------------------------------------------------------------------------------- 1 | {% extends DYNAMICFORMS.field_base_template %} 2 | {% load dynamicforms %} 3 | {% block field_input %} 4 | {% set_var templatename=DYNAMICFORMS.template|add:'field/checkbox_multiple.html' %} 5 | 6 | {% for key, text in field.choices|items %} 7 |
8 | 13 | 14 |
15 | {% endfor %} 16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/field/dict_field.html: -------------------------------------------------------------------------------- 1 | {% extends DYNAMICFORMS.field_base_template %} 2 | {% block field_input %} 3 |

Dictionaries are not currently supported in HTML input.

4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/field/fieldset.html: -------------------------------------------------------------------------------- 1 | {% load dynamicforms %} 2 | {% set_var templatename=DYNAMICFORMS.template|add:'field/fieldset.html' %} 3 | 4 | {% extendtemplate template_name_var=templatename %} 5 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/field/form.html: -------------------------------------------------------------------------------- 1 | {% load dynamicforms %} 2 | 3 | {% set_var templatename=DYNAMICFORMS.template|add:'field/form.html' %} 4 | 5 | {% if form.has_non_field_errors %} 6 | {% for error in form.errors.non_field_errors %} 7 | {% extendtemplateblock template_name_var=templatename block="error_panel" %} 8 | {% block error_class %}text-danger{% endblock %} 9 | {% block error_data %}{{ error }}{% endblock %} 10 | {% endextendtemplateblock %} 11 | {% endfor %} 12 | {% endif %} 13 | 14 | {% block form_inner %} 15 | {% for field in form %} 16 | {% render_field field style=style %} 17 | {% endfor %} 18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/field/list_field.html: -------------------------------------------------------------------------------- 1 | {% extends DYNAMICFORMS.field_base_template %} 2 | {% block field_input %} 3 |

Lists are not currently supported in HTML input.

4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/field/list_fieldset.html: -------------------------------------------------------------------------------- 1 | {% load dynamicforms %} 2 | {% set_var templatename=DYNAMICFORMS.template|add:'field/list_fieldset.html' %} 3 | 4 | {% extendtemplate template_name_var=templatename %} 5 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/field/radio.html: -------------------------------------------------------------------------------- 1 | {% extends DYNAMICFORMS.field_base_template %} 2 | {% load i18n dynamicforms %} 3 | {% trans "None" as none_choice %} 4 | 5 | {% block field_input %} 6 | {% set_var templatename=DYNAMICFORMS.template|add:'field/radio.html' %} 7 | 8 | {% if field.allow_null or field.allow_blank %} 9 |
10 | 13 | 14 |
15 | {% endif %} 16 | 17 | {% for key, text in field.choices|items %} 18 |
19 | 21 | 22 |
23 | {% endfor %} 24 | {% endblock %} 25 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/field/rtf_field.html: -------------------------------------------------------------------------------- 1 | {% extends DYNAMICFORMS.field_base_template %}{% load dynamicforms %} 2 | 3 | {% block field_input %} 4 | {% set_var templatename=DYNAMICFORMS.template|add:'field/rtf_field.html' %} 5 | 6 | 11 | 14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/field/textarea.html: -------------------------------------------------------------------------------- 1 | {% extends DYNAMICFORMS.field_base_template %} 2 | {% load dynamicforms %} 3 | {% block field_input %} 4 | {% set_var templatename=DYNAMICFORMS.template|add:'field/textarea.html' %} 5 | 6 | 13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/base_form.html: -------------------------------------------------------------------------------- 1 | {% load dynamicforms %} 2 | {#This template is extended by dynamicforms/base_form#} 3 | 4 | {% block body %} 5 |
6 |
7 | {% block form_body %}{% endblock %} 8 |
9 |
10 | {% endblock %} 11 | {% block buttons %} 12 | {% block form_buttons %}{% endblock %} 13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/base_list.html: -------------------------------------------------------------------------------- 1 | {% load dynamicforms %} 2 | {#This template is extended by dynamicforms/base_list#} 3 | 4 | {% block table_class %} 5 | table 6 | {% endblock %} 7 | {% block th_definition %} 8 | class="{{ table_classes }} {{ ordering }}" {% if invisible %}style="display: none"{% endif %} 9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/base_table_body.html: -------------------------------------------------------------------------------- 1 | {% load dynamicforms %} 2 | {#This template is included by dynamicforms/base_table_body#} 3 | 4 | class="{{ table_classes }}"{% if invisible %} style="display: none" {% endif %} 5 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/base_table_filter.html: -------------------------------------------------------------------------------- 1 | {#This template is included by dynamicforms/base_table_filter#} 2 | 3 | {% if invisible %}style="display: none" 4 | {% elif no_filter %}style="visibility: hidden" 5 | {% endif %} 6 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/base_field.html: -------------------------------------------------------------------------------- 1 | {% block class_container %} 2 | {% if errors %}ui-error-container{% endif %} 3 | {% if hide_container %}ui-helper-hidden{% else %}dynamicforms-table-row{% endif %} 4 | {% endblock %} 5 | 6 | {% block class_label %} 7 | dynamicforms-label{% if hide_label %} ui-helper-hidden{% endif %} 8 | {% endblock %} 9 | 10 | {% block class_span_error %} 11 | ui-error-span dynamicforms-field-error-message 12 | {% endblock %} 13 | 14 | {% block class_span_help %} 15 | help-block 16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/checkbox.html: -------------------------------------------------------------------------------- 1 | {% block input_class %} 2 | "ui-checkbox-inline{% if not field.label %} position-static{% endif %}" 3 | {% endblock %} 4 | 5 | {% block label_class %} 6 | "{% if style.hide_label %} ui-helper-hidden{% endif %}" 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/checkbox_multiple.html: -------------------------------------------------------------------------------- 1 | {% block input_class %} 2 | {# No extra class#} 3 | "" 4 | {% endblock %} 5 | 6 | {% block label_class %} 7 | {# No extra class#} 8 | "" 9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/fieldset.html: -------------------------------------------------------------------------------- 1 | {% extends DYNAMICFORMS.field_base_template %} 2 | {% load dynamicforms %} 3 | {% block field_input %} 4 |
5 | {% for nested_field in field %} 6 | {% if not nested_field.read_only %} 7 | {% render_field nested_field style=style %} 8 | {% endif %} 9 | {% endfor %} 10 |
11 | {% endblock %} -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/form.html: -------------------------------------------------------------------------------- 1 | {#This template is included by dynamicforms/field/form.html#} 2 | {% block error_panel %} 3 |

{% block error_data %}{% endblock %}

4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/input.html: -------------------------------------------------------------------------------- 1 | {#This template is included by dynamicforms/field/input.html#} 2 | {% block div_password_class %} 3 | input-icons 4 | {% endblock %} 5 | 6 | {% block input_class %} 7 | {% if input_type != "file" %}text ui-widget ui-corner-all dynamicforms-inputs{% else %} form-control-file{% endif %}{% if errors %} ui-state-error{% endif %} 8 | {% endblock %} 9 | 10 | {% block password_toggle %} 11 | {% load dynamicforms %} 12 | {% extendtemplate template_name_var=base_template block="password_span" password_span_visible=True %} 13 | {% endblock %} 14 | 15 | {% block password_span_class %} 16 | ui-icon ui-icon-circle-check 17 | {% endblock %} 18 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/list_fieldset.html: -------------------------------------------------------------------------------- 1 | {% extends DYNAMICFORMS.field_base_template %} 2 | {% block field_input %} 3 |
4 |

Lists are not currently supported in HTML input.

5 |
6 | {% endblock %} 7 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/radio.html: -------------------------------------------------------------------------------- 1 | {#This template is included by dynamicforms/field/radio.html#} 2 | {% block input_class %} 3 | {# No extra class#} 4 | {% endblock %} 5 | 6 | {% block label_class %} 7 | {# No extra class#} 8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/rtf_field.html: -------------------------------------------------------------------------------- 1 | {#This template is included by dynamicforms/field/rtf_field.html#} 2 | {% block field_class %} 3 | ui-widget ui-corner-all dynamicforms-inputs 4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/select.html: -------------------------------------------------------------------------------- 1 | {% block start_copy_span %} 2 | {# jQueryUI nima copy spana#} 3 | {% endblock %} 4 | 5 | {% block select_class %} 6 | ui-widget ui-widget-content ui-state-default ui-corner-all dynamicforms-inputs{% if errors %} ui-state-error{% endif %} 7 | {% endblock %} 8 | 9 | {% block select_style %} 10 | min-width: 6em 11 | {% endblock %} 12 | 13 | {% block end_copy_span %} 14 | {# jQueryUI nima copy spana#} 15 | {% endblock %} 16 | 17 | {% block script_use_select_2 %} 18 | {% if DYNAMICFORMS.use_select2 %} 19 | window.setTimeout(function() { 20 | {% block script_use_select_2_body %}{% endblock %} 21 | }, 1); 22 | {% else %} 23 | // Selectmenus need to be created AFTER the dialog... So use the setTimeout because we don't know the dialog here. 24 | window.setTimeout(function() { 25 | $('#{{ field.uuid }}').selectmenu(); 26 | }, 1); 27 | {% endif %} 28 | 29 | {% endblock %} 30 | 31 | {% block select2_additional_conf %} 32 | , width: '100%', 33 | {% endblock %} 34 | 35 | {% block field_onchange_special_func %} 36 | $('#{{ field.uuid }}').on('selectmenuselect', function () { dynamicforms.fieldChange('{{ field.uuid }}', 'final'); }); 37 | {% endblock %} 38 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/select_multiple.html: -------------------------------------------------------------------------------- 1 | {% block select_class %} 2 | ui-widget ui-widget-content ui-state-default ui-corner-all dynamicforms-inputs {% if errors %} ui-state-error{% endif %} 3 | {% endblock %} 4 | 5 | {% block select_style %} 6 | {% endblock %} 7 | 8 | {% block script_use_select_2 %} 9 | {% if DYNAMICFORMS.use_select2 %} 10 | window.setTimeout(function() { 11 | {% block script_use_select_2_body %}{% endblock %} 12 | }, 1); 13 | {% endif %} 14 | {% endblock %} 15 | 16 | {% block select2_additional_conf %} 17 | //jojojo 18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/textarea.html: -------------------------------------------------------------------------------- 1 | {#This template is included by dynamicforms/field/textarea.html#} 2 | {% block field_class %} 3 | ui-widget ui-corner-all dynamicforms-inputs 4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/modal_dialog.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 |
3 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/modal_dialog_rest.html: -------------------------------------------------------------------------------- 1 | {% load dynamicforms %} 2 | {#This template is extended by dynamicforms/modal_dialog_rest#} 3 | 4 | 28 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/jquery_ui/page.html: -------------------------------------------------------------------------------- 1 | {#This template is extended by dynamicforms/page#} 2 | {% load dynamicforms %} 3 |
4 |
{% block title_header %}{% endblock %} 5 | 6 | {% block render_table_commands %}{% endblock %} 7 | 8 |
9 |
10 | {% block page_body %}{% endblock %} 11 |
12 |
13 | 14 | 21 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/modal_dialog.html: -------------------------------------------------------------------------------- 1 | {% load dynamicforms %} 2 | {% set_var templatename=DYNAMICFORMS.template|add:'modal_dialog.html' %} 3 | 4 | {% extendtemplate template_name_var=templatename %} 5 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/modal_dialog_rest.html: -------------------------------------------------------------------------------- 1 | {% load dynamicforms %} 2 | 3 | {% if data.id %} 4 | {% set_var title=serializer.form_titles.edit %} 5 | {% else %} 6 | {% set_var title=serializer.form_titles.new %} 7 | {% endif %} 8 | 9 | {% set_var templatename=DYNAMICFORMS.template|add:'modal_dialog_rest.html' %} 10 | 11 | {% extendtemplateblock template_name_var=templatename %} 12 | {% block body %} 13 | {% include serializer.template_name with serializer=serializer data=data %} 14 | {% endblock %} 15 | {% block footer %} 16 | {% render_table_commands serializer 'form-buttons' button_position='dialog' %} 17 | {% endblock %} 18 | {% endextendtemplateblock %} 19 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/page.html: -------------------------------------------------------------------------------- 1 | {# TODO: Prestavi, da bo base povlekel podatke iz page-a #} 2 | {% extends DYNAMICFORMS.template_root|add:'base.html' %} 3 | {% load dynamicforms %} 4 | {% block title %} 5 | {{ serializer.page_title }} 6 | {% endblock %} 7 | {% block body %} 8 | {% get_data_template as data_template %} 9 | 10 | {% set_var templatename=DYNAMICFORMS.template|add:'page.html' %} 11 | 12 | {% extendtemplateblock template_name_var=templatename %} 13 | {% block title_header %} 14 | {{ serializer.page_title }} 15 | {% endblock %} 16 | {% block render_table_commands %} 17 | {% if serializer.render_type == 'table' %}{% render_table_commands serializer 'header' %}{% endif %} 18 | {% endblock %} 19 | {% block page_body %} 20 | {% include data_template with serializer=serializer data=data %} 21 | {% endblock %} 22 | {% endextendtemplateblock %} 23 | 24 | {% include DYNAMICFORMS.template_root|add:"modal_dialog.html" %} 25 | {% endblock %} 26 | -------------------------------------------------------------------------------- /dynamicforms_legacy/templates/dynamicforms/rtf_field_style.html: -------------------------------------------------------------------------------- 1 | button.ck.ck-button.ck-heading_alert-primary { 2 | font-size: 1.5em; 3 | color: #004085; 4 | background-color: #cce5ff; 5 | border-color: #b8daff; 6 | } 7 | 8 | button.ck.ck-button.ck-heading_alert-secondary { 9 | font-size: 1.5em; 10 | color: #383d41; 11 | background-color: #e2e3e5; 12 | border-color: #d6d8db; 13 | } 14 | 15 | button.ck.ck-button.ck-heading_alert-success { 16 | font-size: 1.5em; 17 | color: #155724; 18 | background-color: #d4edda; 19 | border-color: #c3e6cb; 20 | } 21 | 22 | button.ck.ck-button.ck-heading_alert-danger { 23 | font-size: 1.5em; 24 | color: #721c24; 25 | background-color: #f8d7da; 26 | border-color: #f5c6cb; 27 | } 28 | 29 | button.ck.ck-button.ck-heading_alert-warning { 30 | font-size: 1.5em; 31 | color: #856404; 32 | background-color: #fff3cd; 33 | border-color: #ffeeba; 34 | } 35 | 36 | button.ck.ck-button.ck-heading_alert-info { 37 | font-size: 1.5em; 38 | color: #0c5460; 39 | background-color: #d1ecf1; 40 | border-color: #bee5eb; 41 | } -------------------------------------------------------------------------------- /dynamicforms_legacy/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/dynamicforms_legacy/templatetags/__init__.py -------------------------------------------------------------------------------- /dynamicforms_legacy/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import re_path 2 | 3 | from dynamicforms_legacy import progress 4 | 5 | urlpatterns = [ 6 | # Progress is used for checking on progress of operation on server 7 | re_path(r"^progress-legacy/$", progress.get_progress_value, name="progress"), 8 | ] 9 | -------------------------------------------------------------------------------- /dynamicforms_legacy/views.py: -------------------------------------------------------------------------------- 1 | # from django.shortcuts import render 2 | -------------------------------------------------------------------------------- /examples/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/examples/__init__.py -------------------------------------------------------------------------------- /examples/admin.py: -------------------------------------------------------------------------------- 1 | 2 | # Register your models here. 3 | -------------------------------------------------------------------------------- /examples/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ExamplesConfig(AppConfig): 5 | name = "examples" 6 | -------------------------------------------------------------------------------- /examples/enum_field.py: -------------------------------------------------------------------------------- 1 | from dynamicforms import fields 2 | 3 | # TODO: #821 - Perhaps standard ChoiceField should support enums out-of-the-box? 4 | # e.g. if choices was an enum, it would resolve it into actual choices as well as support to_representation 5 | 6 | 7 | class EnumField(fields.ChoiceField): 8 | def __init__(self, enum_type, *args, **kwds): 9 | kwds["choices"] = tuple([(member.value, member.name) for member in enum_type]) 10 | super().__init__(*args, **kwds) 11 | self.enum_type = enum_type 12 | 13 | def to_representation(self, value, row_data=None): 14 | if isinstance(value, self.enum_type): 15 | value = value.value 16 | return super().to_representation(value, row_data) 17 | 18 | def render_to_table(self, value, row_data): 19 | try: 20 | if not isinstance(value, self.enum_type): 21 | value = self.enum_type(value) 22 | return value.name 23 | except ValueError: 24 | pass # If the value is not in the enum, just skip to default rendering 25 | return value 26 | -------------------------------------------------------------------------------- /examples/migrations/0002_auto_20190320_0823.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-03-20 08:23 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("examples", "0001_initial"), 9 | ] 10 | 11 | operations = [ 12 | migrations.AlterField( 13 | model_name="basicfields", 14 | name="float_field", 15 | field=models.FloatField(null=True), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /examples/migrations/0003_filter_name.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.1 on 2020-02-25 07:29 2 | 3 | from django.db import migrations, models 4 | 5 | from . import add_filter, add_page_load, add_relation 6 | 7 | 8 | class Migration(migrations.Migration): 9 | dependencies = [ 10 | ("examples", "0002_auto_20190320_0823"), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name="filter", 16 | name="name", 17 | field=models.CharField( 18 | blank=True, help_text="Name field", max_length=20, null=True, verbose_name="Name field" 19 | ), 20 | ), 21 | migrations.RunPython( 22 | lambda apps, schema_editor: add_relation(apps.get_model("examples", "Relation")), atomic=True 23 | ), 24 | migrations.RunPython(lambda apps, schema_editor: add_filter(apps.get_model("examples", "Filter")), atomic=True), 25 | migrations.RunPython( 26 | lambda apps, schema_editor: add_page_load(apps.get_model("examples", "PageLoad")), atomic=True 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /examples/migrations/0004_basicfields_password_field.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.13 on 2020-09-11 12:19 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("examples", "0003_filter_name"), 9 | ] 10 | 11 | operations = [ 12 | migrations.AddField( 13 | model_name="basicfields", 14 | name="password_field", 15 | field=models.CharField(max_length=32, null=True), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /examples/migrations/0005_advancedfields_file_field_two.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.10 on 2020-09-15 07:07 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("examples", "0004_basicfields_password_field"), 9 | ] 10 | 11 | operations = [ 12 | migrations.AddField( 13 | model_name="advancedfields", 14 | name="file_field_two", 15 | field=models.FileField(blank=True, null=True, upload_to="examples2/"), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /examples/migrations/0005_refreshtype_rich_text_field.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.10 on 2020-09-15 14:29 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("examples", "0004_basicfields_password_field"), 9 | ] 10 | 11 | operations = [ 12 | migrations.AddField( 13 | model_name="refreshtype", 14 | name="rich_text_field", 15 | field=models.TextField(blank=True, null=True), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /examples/migrations/0006_merge_20200921_1152.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.10 on 2020-09-21 11:52 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("examples", "0005_advancedfields_file_field_two"), 9 | ("examples", "0005_refreshtype_rich_text_field"), 10 | ] 11 | 12 | operations = [] 13 | -------------------------------------------------------------------------------- /examples/migrations/0007_basicfields_nullint_field.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.13 on 2020-10-27 12:06 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("examples", "0006_merge_20200921_1152"), 9 | ] 10 | 11 | operations = [ 12 | migrations.AddField( 13 | model_name="basicfields", 14 | name="nullint_field", 15 | field=models.IntegerField(null=True), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /examples/migrations/0008_auto_20210303_0904.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.7 on 2021-03-03 09:04 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("examples", "0007_basicfields_nullint_field"), 9 | ] 10 | 11 | operations = [ 12 | migrations.AlterField( 13 | model_name="basicfields", 14 | name="nullboolean_field", 15 | field=models.BooleanField(null=True), 16 | ), 17 | migrations.AlterField( 18 | model_name="basicfields", 19 | name="nullint_field", 20 | field=models.IntegerField(blank=True, null=True), 21 | ), 22 | migrations.AlterField( 23 | model_name="pageload", 24 | name="choice", 25 | field=models.IntegerField( 26 | choices=[(1, "Choice 1"), (2, "Choice 2"), (3, "Choice 3"), (4, "Choice 4")], default=1 27 | ), 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /examples/migrations/0008_auto_20210312_1146.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.13 on 2021-03-12 11:46 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("examples", "0008_auto_20210303_0904"), 9 | ] 10 | 11 | operations = [ 12 | migrations.AddField( 13 | model_name="advancedfields", 14 | name="single_choice_field", 15 | field=models.CharField(max_length=8, null=True), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /examples/migrations/0009_auto_20210929_1136.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.5 on 2021-09-29 11:36 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("examples", "0008_auto_20210312_1146"), 9 | ] 10 | 11 | operations = [ 12 | migrations.CreateModel( 13 | name="Document", 14 | fields=[ 15 | ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), 16 | ("description", models.CharField(help_text="Document description", max_length=30)), 17 | ("file", models.FileField(upload_to="documents/")), 18 | ], 19 | ), 20 | migrations.AlterField( 21 | model_name="basicfields", 22 | name="nullboolean_field", 23 | field=models.BooleanField(blank=True, null=True), 24 | ), 25 | migrations.AlterField( 26 | model_name="hiddenfields", 27 | name="qty_fld", 28 | field=models.FloatField( 29 | blank=True, help_text="Feel free to use a decimal point / comma", null=True, verbose_name="Weight" 30 | ), 31 | ), 32 | ] 33 | -------------------------------------------------------------------------------- /examples/migrations/0010_filter_rtf_field.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.12 on 2021-11-09 07:53 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("examples", "0009_auto_20210929_1136"), 9 | ] 10 | 11 | operations = [ 12 | migrations.AddField( 13 | model_name="filter", 14 | name="rtf_field", 15 | field=models.TextField(blank=True, help_text="RTF Field", null=True, verbose_name="RTF Field"), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /examples/rest/calculated_css_class_for_table_row.py: -------------------------------------------------------------------------------- 1 | from .filter import FilterSerializer, FilterViewSet 2 | 3 | 4 | class CalculatedCssClassForTableRowSerializer(FilterSerializer): 5 | template_context = dict(url_reverse="calculated-css-class-for-table-row") 6 | form_titles = { 7 | "table": "Table with calculated css style for row", 8 | "new": "New object", 9 | "edit": "Editing object", 10 | } 11 | 12 | def get_row_css_style(self, obj): 13 | if obj: 14 | return ( 15 | "color:gold;font-weight:bold;background-color:steelblue;" 16 | if obj.char_field and "abc" in obj.char_field 17 | else "" 18 | ) 19 | return "" 20 | 21 | class Meta(FilterSerializer.Meta): 22 | pass 23 | 24 | 25 | class CalculatedCssClassForTableRowViewSet(FilterViewSet): 26 | serializer_class = CalculatedCssClassForTableRowSerializer 27 | -------------------------------------------------------------------------------- /examples/rest/calendar_reminders.py: -------------------------------------------------------------------------------- 1 | from dynamicforms import fields, serializers 2 | from dynamicforms.viewsets import ModelViewSet 3 | from examples.enum_field import EnumField 4 | from examples.models import CalendarReminder 5 | 6 | 7 | class RemindersSerializer(serializers.ModelSerializer): 8 | template_context = dict(url_reverse="calendar-reminder") 9 | form_titles = { 10 | "table": "Reminders", 11 | "new": "New reminder", 12 | "edit": "Editing reminder", 13 | } 14 | 15 | id = fields.AutoGeneratedField(read_only=False, required=False) 16 | event = fields.AutoGeneratedField(display=serializers.DisplayMode.SUPPRESS, required=False, write_only=True) 17 | type = EnumField(CalendarReminder.RType) 18 | unit = EnumField(CalendarReminder.Unit) 19 | 20 | class Meta: 21 | model = CalendarReminder 22 | fields = ("id", "event", "type", "quantity", "unit") 23 | 24 | 25 | class CalendarRemindersViewSet(ModelViewSet): 26 | queryset = CalendarReminder.objects.all() 27 | serializer_class = RemindersSerializer 28 | -------------------------------------------------------------------------------- /examples/rest/document.py: -------------------------------------------------------------------------------- 1 | from dynamicforms import fields, serializers 2 | from dynamicforms.viewsets import ModelViewSet 3 | 4 | from ..models import Document 5 | 6 | 7 | class DocumentsSerializer(serializers.ModelSerializer): 8 | template_context = dict(url_reverse="documents") 9 | form_titles = { 10 | "table": "Document list", 11 | "new": "New document object", 12 | "edit": "Editing document object", 13 | } 14 | 15 | file = fields.FileField(allow_empty_file=False, use_url=False, allow_null=True) 16 | 17 | class Meta: 18 | model = Document 19 | exclude = () 20 | 21 | 22 | class DocumentsViewset(ModelViewSet): 23 | pagination_class = ModelViewSet.generate_paged_loader(30) 24 | 25 | queryset = Document.objects.all() 26 | serializer_class = DocumentsSerializer 27 | -------------------------------------------------------------------------------- /examples/rest/fields/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/examples/rest/fields/__init__.py -------------------------------------------------------------------------------- /examples/rest/fields/name_field.py: -------------------------------------------------------------------------------- 1 | from dynamicforms import fields 2 | 3 | 4 | class NameTestField(fields.CharField): 5 | def to_representation(self, value, row_data=None): 6 | if not value.pk: 7 | return None 8 | return value.name 9 | 10 | def to_internal_value(self, data): 11 | return {"name": super().to_internal_value(data)} 12 | -------------------------------------------------------------------------------- /examples/rest/page_load.py: -------------------------------------------------------------------------------- 1 | from dynamicforms import serializers, viewsets 2 | from dynamicforms.action import Actions 3 | 4 | from ..models import PageLoad 5 | 6 | 7 | class PageLoadSerializer(serializers.ModelSerializer): 8 | template_context = dict(url_reverse="page-load") 9 | form_titles = { 10 | "table": "Dynamic page loader list", 11 | "new": "New object", 12 | "edit": "Editing object", 13 | } 14 | 15 | actions = Actions(add_default_crud=True, add_default_filter=True) 16 | 17 | def get_row_css_style(self, obj): 18 | return "color: darkred" 19 | 20 | class Meta: 21 | model = PageLoad 22 | exclude = () 23 | 24 | 25 | class PageLoadViewSet(viewsets.ModelViewSet): 26 | template_context = dict(url_reverse="page-load") 27 | pagination_class = viewsets.ModelViewSet.generate_paged_loader(30) # enables pagination 28 | ordering_parameter = "sorting" 29 | ordering_style = "examples.pageLoadOrdering" 30 | 31 | queryset = PageLoad.objects.all() 32 | serializer_class = PageLoadSerializer 33 | -------------------------------------------------------------------------------- /examples/rest/relation.py: -------------------------------------------------------------------------------- 1 | from dynamicforms import fields, serializers 2 | from dynamicforms.viewsets import ModelViewSet 3 | 4 | from ..models import Relation 5 | 6 | 7 | class RelationSerializer(serializers.ModelSerializer): 8 | template_context = dict(url_reverse="relation") 9 | form_titles = { 10 | "table": "Relation fields list", 11 | "new": "New relation object", 12 | "edit": "Editing relation object", 13 | } 14 | 15 | name = fields.CharField() 16 | 17 | class Meta: 18 | model = Relation 19 | exclude = () 20 | 21 | 22 | class RelationViewset(ModelViewSet): 23 | pagination_class = ModelViewSet.generate_paged_loader(30) 24 | 25 | queryset = Relation.objects.all() 26 | serializer_class = RelationSerializer 27 | -------------------------------------------------------------------------------- /examples/rest/write_only_fields.py: -------------------------------------------------------------------------------- 1 | from dynamicforms import fields, serializers 2 | from dynamicforms.mixins import DisplayMode 3 | from dynamicforms.viewsets import ModelViewSet 4 | from examples.models import AdvancedFields 5 | 6 | 7 | class WriteOnlyFieldsSerializer(serializers.ModelSerializer): 8 | template_context = dict(url_reverse="write-only-fields") 9 | form_titles = { 10 | "table": "Write only fields list", 11 | "new": "New write only fields object", 12 | "edit": "Editing write only fields object", 13 | } 14 | 15 | regex_field = fields.CharField(label="Hidden", write_only=True) 16 | choice_field = fields.CharField(label="Shown", write_only=True, display=DisplayMode.FULL) 17 | 18 | class Meta: 19 | model = AdvancedFields 20 | fields = ("id", "regex_field", "choice_field") 21 | 22 | 23 | class WriteOnlyFieldsViewSet(ModelViewSet): 24 | pagination_class = ModelViewSet.generate_paged_loader(30) 25 | 26 | queryset = AdvancedFields.objects.all() 27 | serializer_class = WriteOnlyFieldsSerializer 28 | -------------------------------------------------------------------------------- /examples/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /examples/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import include 2 | from django.urls import path, re_path 3 | from django.views.i18n import JavaScriptCatalog 4 | from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView 5 | 6 | from examples.rest import router 7 | 8 | urlpatterns = [ 9 | re_path(r"^", include(router.urls)), 10 | re_path(r"^dynamicforms/", include("dynamicforms.urls")), 11 | re_path(r"^api-schema/", SpectacularAPIView.as_view(), name="schema"), 12 | re_path(r"^api-docs/", SpectacularRedocView.as_view(url_name="schema")), 13 | path("jsi18n/", JavaScriptCatalog.as_view(), name="javascript-catalog"), 14 | ] 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dynamicform-project", 3 | "private": false, 4 | "version": "0.10.00", 5 | "description": "Data entry boilerplate components and a RESTful API consumer", 6 | "author": "Jure Erznožnik", 7 | "workspaces": [ 8 | "vue/*" 9 | ], 10 | "scripts": { 11 | "clean": "rf", 12 | "dev": "npm run dev -ws --if-present", 13 | "preview": "npm run build -w @velis/dynamicforms && npm run preview -w demo", 14 | "build": "npm run build -ws --if-present", 15 | "build-no-tsc": "npm run build-no-tsc -ws --if-present", 16 | "publish": "npm run build || cd vue/dynamicforms && np && cd ../..", 17 | "test": "npm run test -ws --if-present", 18 | "lint": "npm run lint -ws --if-present", 19 | "docs:dev": "vitepress dev docs", 20 | "docs:build": "vitepress build docs", 21 | "docs:preview": "vitepress preview docs" 22 | }, 23 | "devDependencies": { 24 | "typescript": "^5", 25 | "vitepress": "^1.3.2" 26 | }, 27 | "eslintConfig": { 28 | "extends": [ 29 | "velis" 30 | ], 31 | "rules": { 32 | "vuejs-accessibility/click-events-have-key-events": "off", 33 | "vuejs-accessibility/form-control-has-label": "off", 34 | "vuejs-accessibility/label-has-for": "off" 35 | }, 36 | "ignorePatterns": [ 37 | "dist/*", 38 | "coverage/*", 39 | "node_modules/*" 40 | ] 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /readthedocs.yml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yml 2 | 3 | build: 4 | image: latest 5 | 6 | python: 7 | version: 3.6 8 | setup_py_install: true 9 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pytz 2 | coreapi>=1.32 3 | django>=2 4 | djangorestframework>=3.14 5 | django-filter 6 | django-enumfields >= 2.1.1 7 | jsonschema 8 | pillow 9 | django-cors-headers 10 | versio 11 | ruff 12 | ruff-lsp 13 | six 14 | drf_spectacular 15 | -------------------------------------------------------------------------------- /requirements_test_functional.txt: -------------------------------------------------------------------------------- 1 | selenium 2 | tox 3 | flake8 4 | isort 5 | parameterized 6 | coverage 7 | django_coverage_plugin 8 | -------------------------------------------------------------------------------- /setup/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/setup/__init__.py -------------------------------------------------------------------------------- /setup/urls.py: -------------------------------------------------------------------------------- 1 | """dynamic forms URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/1.10/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.conf.urls import url, include 14 | 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) 15 | """ 16 | from django.conf.urls import include 17 | from django.conf.urls.static import static 18 | from django.contrib import admin 19 | from django.urls import re_path 20 | 21 | from setup import settings 22 | 23 | urlpatterns = [ 24 | re_path(r"^", include("examples.urls")), 25 | re_path(r"^admin/", admin.site.urls), 26 | ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 27 | -------------------------------------------------------------------------------- /setup/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for dynamic forms project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "setup.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/tests/__init__.py -------------------------------------------------------------------------------- /tests/functional/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/tests/functional/__init__.py -------------------------------------------------------------------------------- /tests/static_files/0_3142.prj: -------------------------------------------------------------------------------- 1 | PROJCS["North_America_Lambert_Conformal_Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-117.9388888888889],PARAMETER["Standard_Parallel_1",43.80527441355559],PARAMETER["Standard_Parallel_2",43.86083547742365],PARAMETER["Latitude_Of_Origin",40.0],UNIT["Meter",1.0]] -------------------------------------------------------------------------------- /tests/unit/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velis74/DynamicForms/e3061a79c16996535a56adf8bf7f18e7f9cd0726/tests/unit/__init__.py -------------------------------------------------------------------------------- /tests/unit/test_df_serializer.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from django.test.client import RequestFactory 3 | 4 | from dynamicforms.template_render import ViewModeSerializer 5 | from examples.rest.validated import ValidatedSerializer, ValidatedViewSet 6 | 7 | 8 | class SerializerTest(TestCase): 9 | def setUp(self): 10 | self.factory = RequestFactory() 11 | 12 | def test_show_filter(self): 13 | request = self.factory.get("/validated/") 14 | request.accepted_renderer = None 15 | 16 | viewset = ValidatedViewSet() 17 | viewset.request = request 18 | 19 | serializer = ValidatedSerializer(context={"request": request, "view": viewset}) 20 | serializer.show_filter = True 21 | serializer.view_mode = ViewModeSerializer.ViewMode.TABLE_ROW 22 | serializer.apply_component_context(request) 23 | res = serializer.component_params(output_json=False) 24 | filter_value = res["filter"] 25 | self.assertIsNotNone(filter_value) 26 | 27 | serializer.show_filter = False 28 | res = serializer.component_params(output_json=False) 29 | filter_value = res["filter"] 30 | self.assertIsNone(filter_value) 31 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | # tox (https://tox.readthedocs.io/) is a tool for running tests 2 | # in multiple virtualenvs. This configuration file will run the 3 | # test suite on all supported python versions. To use it, "pip install tox" 4 | # and then run "tox" from this directory. 5 | 6 | [tox] 7 | envlist = 8 | django32-drf{314} 9 | django42-drf{314,tip} 10 | djangotip-drftip 11 | check 12 | doc 13 | 14 | skipsdist = True 15 | 16 | [testenv] 17 | deps = 18 | -r{toxinidir}/requirements.txt 19 | 20 | django32: django==3.2.* 21 | django42: django==4.2.* 22 | djangotip: https://github.com/django/django/archive/main.tar.gz 23 | drf314: djangorestframework==3.14.* 24 | drftip: https://github.com/encode/django-rest-framework/archive/master.tar.gz 25 | typing: typing 26 | django-filter 27 | pillow 28 | selenium 29 | versio 30 | parameterized 31 | six 32 | drf_spectacular 33 | 34 | commands = 35 | python manage.py test 36 | 37 | [testenv:check] 38 | deps = 39 | -r{toxinidir}/requirements.txt 40 | 41 | commands = 42 | ruff check --diff 43 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "declaration": true, 5 | "declarationMap": true, 6 | "sourceMap": true, 7 | "outDir": "./dist", 8 | "skipLibCheck": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": [ 4 | "vue/demo/src/**/*", 5 | "vue/dynamicforms/src/**/*" 6 | ], 7 | "exclude": [ 8 | "dist", 9 | "node_modules", 10 | "tests" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/eslint-config-velis/tsconfig.json", 3 | "include": ["vue/**/*"], 4 | "exclude": [ 5 | "dist", 6 | "coverage", 7 | "dynamicforms", 8 | "node_modules" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /vue/demo/.env: -------------------------------------------------------------------------------- 1 | VITE_AXIOS_TARGET=http://localhost:8000 2 | -------------------------------------------------------------------------------- /vue/demo/.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | 3 | dist 4 | 5 | node_modules 6 | -------------------------------------------------------------------------------- /vue/demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /vue/demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo", 3 | "version": "1.0.0", 4 | "type": "module", 5 | "scripts": { 6 | "dev": "vite", 7 | "preview": "vite --mode preview" 8 | }, 9 | "dependencies": { 10 | "@dynamicforms/vuetify-inputs": "^0.2.4", 11 | "@fullcalendar/core": "^6.1.4", 12 | "@fullcalendar/daygrid": "^6.1.4", 13 | "@fullcalendar/interaction": "^6.1.4", 14 | "@fullcalendar/list": "^6.1.4", 15 | "@fullcalendar/moment": "^6.1.4", 16 | "@fullcalendar/moment-timezone": "^6.1.4", 17 | "@fullcalendar/resource-timegrid": "^6.1.4", 18 | "@fullcalendar/timegrid": "^6.1.4", 19 | "@fullcalendar/vue3": "^6.1.4", 20 | "@mdi/font": "^7.4.47", 21 | "@velis/dynamicforms": "*", 22 | "axios": "^1.8.4", 23 | "lodash-es": "^4.17.12", 24 | "suncalc": "^1.9.0", 25 | "vue": "^3", 26 | "vue-ionicon": "^2.1.0", 27 | "vue-router": "^4", 28 | "vuetify": "^3" 29 | }, 30 | "devDependencies": { 31 | "@vitejs/plugin-vue": "^5", 32 | "@types/suncalc": "^1.9.0", 33 | "@types/lodash-es": "^4.17.12", 34 | "http-proxy-middleware": "^3.0.5", 35 | "typescript": "^5", 36 | "vite": "^6.3.2", 37 | "vite-plugin-vuetify": "^2", 38 | "vite-plugin-eslint": "^1.8.1" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /vue/demo/src/demo-app/demo-app.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 36 | -------------------------------------------------------------------------------- /vue/demo/src/demo-app/index.ts: -------------------------------------------------------------------------------- 1 | import DemoApp from './demo-app.vue'; 2 | 3 | export default DemoApp; 4 | -------------------------------------------------------------------------------- /vue/demo/src/demo-app/named-component-loader.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 17 | -------------------------------------------------------------------------------- /vue/demo/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | 3 | import DemoApp from './demo-app'; 4 | import DfViewMode from './demo-app/vuetify/view-mode.vue'; 5 | import dynamicForms from './plugins/dynamic-forms'; 6 | import vuetify from './plugins/vuetify'; 7 | import router from './router'; 8 | 9 | import 'vuetify/styles/main.css'; 10 | import '@mdi/font/css/materialdesignicons.css'; 11 | // eslint-disable-next-line import/no-relative-packages 12 | import '../../dynamicforms/dist/dynamicforms.css'; 13 | import '@dynamicforms/vuetify-inputs/styles.css'; 14 | 15 | const app = createApp(DemoApp); 16 | app.use(router); 17 | app.use(vuetify); 18 | app.use(dynamicForms); 19 | 20 | // demo specific components 21 | app.component('DfViewMode', DfViewMode); 22 | 23 | app.mount('#app'); 24 | -------------------------------------------------------------------------------- /vue/demo/src/plugins/dynamic-forms.ts: -------------------------------------------------------------------------------- 1 | import { createDynamicForms } from 'dynamicforms'; 2 | import type { DynamicFormsOptions } from 'dynamicforms'; 3 | 4 | const options: DynamicFormsOptions = { ui: 'vuetify' }; 5 | 6 | export default createDynamicForms(options); 7 | -------------------------------------------------------------------------------- /vue/demo/src/plugins/vuetify.ts: -------------------------------------------------------------------------------- 1 | import { createVuetify } from 'vuetify'; 2 | import { ThemeDefinition } from 'vuetify/dist/vuetify'; 3 | 4 | const defaultTheme: ThemeDefinition = { 5 | dark: false, 6 | colors: { 7 | background: '#f8f8f8', 8 | surface: '#ffffff', 9 | // 'primary-darken-1': '#3700B3', 10 | // 'secondary-darken-1': '#018786', 11 | primary: '#3f51b5', 12 | secondary: '#2196f3', 13 | accent: '#ffc107', 14 | error: '#f44336', 15 | warning: '#ff9800', 16 | info: '#8bc34a', 17 | success: '#00bcd4', 18 | }, 19 | }; 20 | 21 | const vuetify = createVuetify({ 22 | defaults: { global: {} }, 23 | theme: { defaultTheme: 'defaultTheme', themes: { defaultTheme } }, 24 | }); 25 | 26 | export default vuetify; 27 | -------------------------------------------------------------------------------- /vue/demo/src/router.ts: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHashHistory, RouteLocationNormalized } from 'vue-router'; 2 | 3 | import routes from './routes'; 4 | 5 | const router = createRouter({ 6 | // @ts-ignore 7 | history: createWebHashHistory(import.meta.env.BASE_URL), 8 | routes, 9 | }); 10 | 11 | router.afterEach((to: RouteLocationNormalized) => { 12 | document.title = String(to.meta.title || 'Vite App'); 13 | }); 14 | 15 | export default router; 16 | -------------------------------------------------------------------------------- /vue/demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../dynamicforms/tsconfig.json", 3 | "compilerOptions": { 4 | "paths": { 5 | "dynamicforms": ["../dynamicforms/src/index.ts"], 6 | "@/*": ["../dynamicforms/src/components/*"], 7 | "~/*": ["../../node_modules/*"] 8 | } 9 | }, 10 | "include": ["src/**/*"], 11 | "exclude": [ 12 | "dist", 13 | "coverage", 14 | "node_modules" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /vue/dynamicforms/.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | 3 | dist 4 | 5 | node_modules 6 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/adapters/api/index.ts: -------------------------------------------------------------------------------- 1 | import { IView, IViewSet, IViewSetApi } from './namespace'; 2 | import ViewApi from './view-api'; 3 | import ViewGeneric from './view-generic'; 4 | import ViewSetApi from './view-set-api'; 5 | import ViewSetGeneric from './view-set-generic'; 6 | 7 | export { 8 | ViewGeneric, 9 | ViewApi, 10 | ViewSetGeneric, 11 | ViewSetApi, 12 | }; 13 | 14 | export type { 15 | IView, 16 | IViewSet, 17 | IViewSetApi, 18 | }; 19 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/adapters/api/view-api.ts: -------------------------------------------------------------------------------- 1 | import { IView } from './namespace'; 2 | import ViewGeneric from './view-generic'; 3 | 4 | export default class ViewApi extends ViewGeneric implements IView { 5 | constructor(url: string) { 6 | const baseUrl = url.replace(/\/+$/, ''); 7 | const trailingSlash = `${baseUrl}/`; 8 | super(baseUrl, trailingSlash, trailingSlash, trailingSlash); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/adapters/api/view-generic.ts: -------------------------------------------------------------------------------- 1 | import { AxiosRequestConfig } from 'axios'; 2 | 3 | import { IView } from './namespace'; 4 | 5 | import { apiClient } from '@/util'; 6 | 7 | export default class ViewGeneric implements IView { 8 | protected get_url: string; 9 | 10 | protected post_url: string; 11 | 12 | protected update_url: string; 13 | 14 | protected delete_url: string; 15 | 16 | constructor(get_url: string, post_url: string, update_url: string, delete_url: string) { 17 | this.get_url = get_url; 18 | this.post_url = post_url; 19 | this.update_url = update_url; 20 | this.delete_url = delete_url; 21 | } 22 | 23 | retrieve = async (config?: AxiosRequestConfig): Promise => ( 24 | (await apiClient.get(this.get_url, config)).data 25 | ); 26 | 27 | create = async (data: T, config?: AxiosRequestConfig): Promise => ( 28 | (await apiClient.post(this.post_url, data, config)).data 29 | ); 30 | 31 | update = async (data: T, config?: AxiosRequestConfig): Promise => ( 32 | (await apiClient.put(this.update_url, data, config)).data 33 | ); 34 | 35 | delete = async (config?: AxiosRequestConfig): Promise => ( 36 | (await apiClient.delete(this.delete_url, config)).data 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/adapters/api/view-set-generic.ts: -------------------------------------------------------------------------------- 1 | import { AxiosRequestConfig } from 'axios'; 2 | 3 | import { IViewSet } from './namespace'; 4 | import ViewGeneric from './view-generic'; 5 | 6 | import { apiClient } from '@/util'; 7 | 8 | export default class ViewSetGeneric extends ViewGeneric implements IViewSet { 9 | protected list_url: string; 10 | 11 | constructor(list_url: string, get_url: string, post_url: string, update_url: string, delete_url: string) { 12 | super(get_url, post_url, update_url, delete_url); 13 | this.list_url = list_url; 14 | } 15 | 16 | list = async (config: AxiosRequestConfig | undefined): Promise => ( 17 | (await apiClient.get(this.list_url, config)).data 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/adapters/namespace.ts: -------------------------------------------------------------------------------- 1 | import { APIConsumer } from '../api_consumer/namespace'; 2 | 3 | type MaybeAwaitable = Promise | T; 4 | 5 | export interface FormAdapter { 6 | componentDefinition: () => MaybeAwaitable 7 | retrieve: () => MaybeAwaitable 8 | create: (data: T) => MaybeAwaitable 9 | update: (data: T) => MaybeAwaitable 10 | delete: () => MaybeAwaitable 11 | } 12 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/api_consumer/component-display.ts: -------------------------------------------------------------------------------- 1 | enum ComponentDisplay { 2 | // This enum is actually declared in dynamicforms.mixins.field_render.py 3 | TABLE = 1, 4 | FORM = 2, 5 | DIALOG = 3, 6 | } 7 | 8 | namespace ComponentDisplay { 9 | export function fromString(display: string) { 10 | if (display.toUpperCase() === 'TABLE') return ComponentDisplay.TABLE; 11 | if (display.toUpperCase() === 'FORM') return ComponentDisplay.FORM; 12 | if (display.toUpperCase() === 'DIALOG') return ComponentDisplay.DIALOG; 13 | return ComponentDisplay.TABLE; 14 | } 15 | 16 | export function isDefined(display: number | string) { 17 | const check = (typeof display === 'number') ? display : ComponentDisplay.fromString(display as string); 18 | return Object.values(ComponentDisplay).includes(check); 19 | } 20 | } 21 | 22 | Object.freeze(ComponentDisplay); 23 | 24 | export default ComponentDisplay; 25 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/api_consumer/form-consumer/api.spec.ts: -------------------------------------------------------------------------------- 1 | import MockAdapter from 'axios-mock-adapter'; 2 | import { ref } from 'vue'; 3 | 4 | import FormConsumerApi from './api'; 5 | import data from './api.spec.json'; 6 | 7 | import { apiClient } from '@/util'; 8 | 9 | const mock = new MockAdapter(apiClient); 10 | 11 | const testUrl = '/test'; 12 | 13 | const pk = ref(1); 14 | 15 | describe('Form Consumer API', () => { 16 | afterEach(() => { 17 | mock.reset(); 18 | }); 19 | 20 | it('Create', () => { 21 | const consumer = new FormConsumerApi({ url: testUrl }); 22 | expectTypeOf(consumer).toMatchTypeOf(); 23 | }); 24 | 25 | it('Delete', async () => { 26 | const replyFn = vi.fn(() => [200, data]); 27 | 28 | const deleteFn = vi.fn(() => [200]); 29 | 30 | mock.onGet('/test/1.componentdef').reply(replyFn); 31 | mock.onDelete('/test/1').reply(deleteFn); 32 | const consumer = new FormConsumerApi({ url: testUrl, pk }); 33 | await expect(consumer.delete).rejects.toThrow(); 34 | 35 | expect(replyFn.mock.calls.length).toBe(0); 36 | await consumer.getUXDefinition(); 37 | expect(replyFn.mock.calls.length).toBe(1); 38 | 39 | await expect(consumer.delete()).resolves.not.toThrow(); 40 | expect(deleteFn.mock.calls.length).toBe(1); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/api_consumer/form-consumer/api.ts: -------------------------------------------------------------------------------- 1 | import type { ActionsNS } from '../../actions/namespace'; 2 | import DetailViewApi from '../../adapters/api/detail-view-api'; 3 | import { DetailViewOptions } from '../../adapters/api/namespace'; 4 | 5 | import FormConsumerBase from './base'; 6 | import type { FormConsumerHooks } from './namespace'; 7 | 8 | type IHandlers = ActionsNS.IHandlers; 9 | 10 | class FormConsumerApi extends FormConsumerBase { 11 | declare beforeDialog?: (consumer: FormConsumerApi, ...params: any[]) => any; 12 | 13 | declare afterDialog?: (instance: FormConsumerApi, action: any) => void; 14 | 15 | constructor( 16 | apiOptions: DetailViewOptions, 17 | actionHandlers?: IHandlers, 18 | hooks?: FormConsumerHooks, 19 | ) { 20 | super(actionHandlers, hooks); 21 | 22 | this.api = new DetailViewApi(apiOptions); 23 | } 24 | } 25 | 26 | export default FormConsumerApi; 27 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/api_consumer/form-consumer/array.ts: -------------------------------------------------------------------------------- 1 | import type { ActionsNS } from '../../actions/namespace'; 2 | import InMemoryImplementation, { InMemoryParams } from '../../adapters'; 3 | 4 | import FormConsumerBase from './base'; 5 | import type { FormConsumerHooks } from './namespace'; 6 | 7 | type IHandlers = ActionsNS.IHandlers; 8 | 9 | export default class FormConsumerArray extends FormConsumerBase { 10 | declare beforeDialog?: (instance: FormConsumerArray) => void; 11 | 12 | declare afterDialog?: (instance: FormConsumerArray, action: any) => void; 13 | 14 | constructor( 15 | params: InMemoryParams, 16 | actionHandlers?: IHandlers, 17 | hooks?: FormConsumerHooks, 18 | ) { 19 | super(actionHandlers, hooks); 20 | 21 | this.api = new InMemoryImplementation(params); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/api_consumer/form-consumer/index.ts: -------------------------------------------------------------------------------- 1 | import FormConsumerApi from './api'; 2 | import FormConsumerArray from './array'; 3 | import FormConsumerBase from './base'; 4 | 5 | export { 6 | FormConsumerApi, 7 | FormConsumerArray, 8 | FormConsumerBase, 9 | }; 10 | 11 | export * from './one-shot'; 12 | export * from './namespace'; 13 | 14 | export default FormConsumerApi; 15 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/api_consumer/form-consumer/namespace.ts: -------------------------------------------------------------------------------- 1 | import type { ActionsNS } from '../../actions/namespace'; 2 | import DialogDefinition from '../../modal/dialog-definition'; 3 | 4 | export interface FormResult { 5 | action: ActionsNS.ActionJSON 6 | dialog: DialogDefinition 7 | extraData: unknown 8 | } 9 | 10 | export interface FormConsumerHooks { 11 | beforeDialog?: (instance: T, ...params: any[]) => any; 12 | afterDialog?: (instance: T, action: any) => void; 13 | } 14 | 15 | export interface FormExecuteResult { 16 | data: Partial, 17 | action: FormResult, 18 | } 19 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/api_consumer/form-consumer/one-shot/api.spec.ts: -------------------------------------------------------------------------------- 1 | import MockAdapter from 'axios-mock-adapter'; 2 | 3 | import FormConsumerOneShotApi from './api'; 4 | import data from './api.spec.json'; 5 | 6 | import { apiClient } from '@/util'; 7 | 8 | const mock = new MockAdapter(apiClient); 9 | 10 | let emitted = false; 11 | 12 | const waitForEmitted = async () => Promise.race([async () => { 13 | // eslint-disable-next-line no-constant-condition 14 | while (true) { 15 | if (emitted) { return; } 16 | // eslint-disable-next-line no-await-in-loop 17 | await null; 18 | } 19 | }, new Promise((resolve) => { setTimeout(resolve, 300); })]); 20 | 21 | const replyFn = vi.fn(() => { 22 | emitted = true; 23 | return [200, data]; 24 | }); 25 | 26 | describe('Api One Shot', () => { 27 | afterEach(() => { 28 | mock.reset(); 29 | emitted = false; 30 | }); 31 | 32 | it('Create', async () => { 33 | mock.onGet('/test.componentdef').reply(replyFn); 34 | 35 | FormConsumerOneShotApi({ url: '/test' }); 36 | 37 | // wait for api call 38 | await waitForEmitted(); 39 | 40 | expect(emitted).toBe(true); 41 | expect(replyFn).toBeCalled(); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/api_consumer/form-consumer/one-shot/api.ts: -------------------------------------------------------------------------------- 1 | import type { ActionsNS } from '../../../actions/namespace'; 2 | import { DetailViewOptions } from '../../../adapters/api/namespace'; 3 | import FormConsumerApi from '../api'; 4 | 5 | import FormConsumerOneShotBase from './base'; 6 | 7 | type IHandlers = ActionsNS.IHandlers; 8 | 9 | export default async function FormConsumerOneShotApi( 10 | apiOptions: DetailViewOptions, 11 | handlers?: IHandlers, 12 | ): Promise { 13 | const formConsumer = new FormConsumerApi(apiOptions, handlers); 14 | 15 | return FormConsumerOneShotBase(formConsumer); 16 | } 17 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/api_consumer/form-consumer/one-shot/array.spec.ts: -------------------------------------------------------------------------------- 1 | import FormConsumerOneShotArray from './array'; 2 | import ux_def from './array.spec.json'; 3 | 4 | const mockFn = vi.hoisted(() => vi.fn()); 5 | 6 | vi.mock('./base', () => ({ default: mockFn })); 7 | 8 | describe('Array One Shot', () => { 9 | it('Create', async () => { 10 | await FormConsumerOneShotArray({ definition: ux_def, data: [] }); 11 | 12 | expect(mockFn.mock.calls.length).toBe(1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/api_consumer/form-consumer/one-shot/array.ts: -------------------------------------------------------------------------------- 1 | import type { ActionsNS } from '../../../actions/namespace'; 2 | import { InMemoryParams } from '../../../adapters'; 3 | import FormConsumerArray from '../array'; 4 | 5 | import FormConsumerOneShotBase from './base'; 6 | 7 | type IHandlers = ActionsNS.IHandlers; 8 | 9 | export default async function FormConsumerOneShotArray( 10 | params: InMemoryParams, 11 | handlers?: IHandlers, 12 | ): Promise { 13 | const formConsumer = new FormConsumerArray(params, handlers); 14 | 15 | return FormConsumerOneShotBase(formConsumer); 16 | } 17 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/api_consumer/form-consumer/one-shot/base.ts: -------------------------------------------------------------------------------- 1 | import FormConsumerBase from '../base'; 2 | 3 | export default async function FormConsumerOneShotBase( 4 | formConsumer: FormConsumerBase, 5 | ): Promise { 6 | let error = {}; 7 | let result: T | undefined; 8 | let data: Partial | undefined; 9 | 10 | await formConsumer.getUXDefinition(); 11 | 12 | do { 13 | // eslint-disable-next-line no-await-in-loop 14 | const formResult = await formConsumer.withErrors(error).execute(data); 15 | 16 | const resultAction = formResult.action; 17 | data = formResult.data; 18 | 19 | error = {}; 20 | 21 | if (resultAction.action.name === 'submit') { 22 | try { 23 | // eslint-disable-next-line no-await-in-loop 24 | result = await formConsumer.save(); 25 | } catch (err: any) { 26 | error = { ...err?.response?.data }; 27 | } 28 | } else if (resultAction.action.name === 'delete_dlg') { 29 | try { 30 | // eslint-disable-next-line no-await-in-loop 31 | result = await formConsumer.delete(); 32 | } catch (err: any) { 33 | error = { ...err.response.data }; 34 | } 35 | } 36 | // propagate error to the next dialog 37 | } while (error && Object.keys(error).length); 38 | 39 | return result; 40 | } 41 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/api_consumer/form-consumer/one-shot/index.ts: -------------------------------------------------------------------------------- 1 | import FormConsumerOneShotApi from './api'; 2 | import FormConsumerOneShotArray from './array'; 3 | import FormConsumerOneShotBase from './base'; 4 | 5 | export { 6 | FormConsumerOneShotBase, 7 | FormConsumerOneShotApi, 8 | FormConsumerOneShotArray, 9 | }; 10 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/api_consumer/index-temporary.ts: -------------------------------------------------------------------------------- 1 | import APIConsumerLoader from './api-consumer-loader.vue'; 2 | import APIConsumer from './api-consumer.vue'; 3 | import ComponentDisplay from './component-display'; 4 | import ConsumerLogicApi from './consumer-logic-api'; 5 | 6 | export { ComponentDisplay, APIConsumer, APIConsumerLoader, ConsumerLogicApi }; 7 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/df-app.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/form/definitions/field-render-params.ts: -------------------------------------------------------------------------------- 1 | import { DfForm } from '../namespace'; 2 | 3 | export default class RenderParams { 4 | inputType: string; 5 | 6 | fieldCSSClass?: string; 7 | 8 | pattern?: string; 9 | 10 | min?: number; 11 | 12 | max?: number; 13 | 14 | minLength: number; 15 | 16 | maxLength: number; 17 | 18 | step?: number; 19 | 20 | size?: number; 21 | 22 | formFormat?: string; 23 | 24 | multiple?: boolean; 25 | 26 | allowTags?: boolean; 27 | 28 | formComponentDef?: DfForm.FormComponentDefinition; 29 | 30 | constructor(params: DfForm.RenderParamsJSON) { 31 | this.inputType = params.input_type; 32 | this.fieldCSSClass = params.field_class; 33 | 34 | // Text input 35 | this.pattern = params.pattern; 36 | this.min = params.min; 37 | this.max = params.max; 38 | this.minLength = params.min_length ?? 0; 39 | this.maxLength = params.max_length ?? 1E20; 40 | 41 | // text input, translated into HTML attributes 42 | this.step = params.step; 43 | this.size = params.size; 44 | 45 | // DateTime 46 | this.formFormat = params.form_format; 47 | 48 | // select 49 | this.multiple = params.multiple; 50 | this.allowTags = params.allow_tags; 51 | 52 | // form definition 53 | this.formComponentDef = params.form_component_def; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/form/inputs/date-time.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 33 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/form/inputs/df-checkbox.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 25 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/form/inputs/df-ckeditor.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 27 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/form/inputs/df-color.vue: -------------------------------------------------------------------------------- 1 | 11 | 24 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/form/inputs/df-input.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 34 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/form/inputs/df-placeholder.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 22 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/form/inputs/input-vuetify.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 29 | 30 | 33 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/form/inputs/text-area.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 30 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/modal/definitions/dialog-size.ts: -------------------------------------------------------------------------------- 1 | enum DialogSize { 2 | SMALL = 1, 3 | MEDIUM = 2, 4 | LARGE = 3, 5 | X_LARGE = 4, 6 | DEFAULT = 0, 7 | } 8 | 9 | export const defaultDialogSize: DialogSize = DialogSize.DEFAULT; 10 | 11 | namespace DialogSize { 12 | const largeIdentifiers: string[] = ['large', 'lg', 'modal-lg']; 13 | const mediumIdentifiers: string[] = ['medium', 'md', 'modal-md']; 14 | const smallIdentifiers: string[] = ['small', 'sm', 'modal-sm']; 15 | const xLargeIdentifiers: string[] = ['x-large', 'xl', 'modal-xl']; 16 | 17 | export function fromString(size?: string): DialogSize { 18 | if (size === undefined) return defaultDialogSize; 19 | if (largeIdentifiers.includes(size)) return DialogSize.LARGE; 20 | if (mediumIdentifiers.includes(size)) return DialogSize.MEDIUM; 21 | if (smallIdentifiers.includes(size)) return DialogSize.SMALL; 22 | if (xLargeIdentifiers.includes(size)) return DialogSize.X_LARGE; 23 | return defaultDialogSize; 24 | } 25 | 26 | export function isDefined(size: number | string) { 27 | const check = (typeof size === 'number') ? size : DialogSize.fromString(size as string); 28 | return Object.values(DialogSize).includes(check); 29 | } 30 | } 31 | 32 | Object.freeze(DialogSize); 33 | export default DialogSize; 34 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/modal/index.ts: -------------------------------------------------------------------------------- 1 | import DfDialog from './modal'; 2 | import ModalView from './modal-view'; 3 | 4 | export { DfDialog, ModalView }; 5 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/table/cell-renderers/index.ts: -------------------------------------------------------------------------------- 1 | import TableCellDateTime from './table-cell-date-time.vue'; 2 | import TableCellFloat from './table-cell-float.vue'; 3 | 4 | export { TableCellDateTime, TableCellFloat }; 5 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/table/cell-renderers/table-cell-date-time.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 33 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/table/column-group.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 29 | 32 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/table/definitions/column-ordering-direction.spec.ts: -------------------------------------------------------------------------------- 1 | import OrderingDirection from './column-ordering-direction'; 2 | 3 | describe('OrderingDirection', () => { 4 | // eslint-disable-next-line no-undef 5 | it('Basic enum checks', () => { 6 | expect(OrderingDirection.isDefined(OrderingDirection.ASC)).toStrictEqual(true); // isinstance check 7 | expect(OrderingDirection.ASC).not.toStrictEqual(OrderingDirection.DESC); 8 | expect(OrderingDirection.ASC).toStrictEqual(OrderingDirection.fromString('asc')); 9 | expect(OrderingDirection.isDefined(2)).toStrictEqual(true); 10 | expect(OrderingDirection.isDefined(3)).toStrictEqual(false); 11 | expect(OrderingDirection[OrderingDirection.ASC]).toStrictEqual('ASC'); 12 | expect(OrderingDirection.fromString('asc')).toStrictEqual(OrderingDirection.ASC); 13 | expect(OrderingDirection.fromString('ASC')).toStrictEqual(OrderingDirection.ASC); 14 | expect(OrderingDirection.fromString('desc')).toStrictEqual(OrderingDirection.DESC); 15 | expect(OrderingDirection.fromString('a')).toStrictEqual(OrderingDirection.UNORDERED); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/table/definitions/column-ordering-direction.ts: -------------------------------------------------------------------------------- 1 | enum OrderingDirection { 2 | ASC = 1 as number, 3 | DESC = 2 as number, 4 | UNORDERED = 0 as number, 5 | } 6 | 7 | namespace OrderingDirection { 8 | export function fromString(ordering: string) { 9 | if (ordering.toLowerCase().includes('asc')) return OrderingDirection.ASC; 10 | if (ordering.toLowerCase().includes('desc')) return OrderingDirection.DESC; 11 | return OrderingDirection.UNORDERED; 12 | } 13 | 14 | export function isDefined(ordering: number) { 15 | return Object.values(OrderingDirection).includes(ordering); 16 | } 17 | } 18 | 19 | /* 20 | const OrderingDirection1 = { 21 | ASC: 1 as number, 22 | DESC: 2 as number, 23 | UNORDERED: 0 as number, 24 | 25 | fromString(ordering: string) { 26 | if (ordering.includes('asc')) return OrderingDirection.ASC; 27 | if (ordering.includes('desc')) return OrderingDirection.DESC; 28 | return OrderingDirection.UNORDERED; 29 | }, 30 | 31 | isDefined(ordering: number) { 32 | const allValues = [this.ASC, this.DESC, this.UNORDERED]; 33 | return allValues.includes(ordering); 34 | }, 35 | } as const; 36 | */ 37 | 38 | Object.freeze(OrderingDirection); 39 | export default OrderingDirection; 40 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/table/definitions/columns.ts: -------------------------------------------------------------------------------- 1 | import { reactive } from 'vue'; 2 | 3 | import TableColumn from './column'; 4 | 5 | export default class TableColumns extends Array { 6 | constructor(columnNames: string[], fields: { [key: string]: any }) { 7 | super(); 8 | 9 | if (!(columnNames && fields)) return; // If Array default constructors are called, we don't handle our logic 10 | 11 | const orderingArray = reactive([]); 12 | const res = columnNames.map((columnName: string) => new TableColumn(fields[columnName], orderingArray)); 13 | 14 | // We will also clear any non-assigned sorting segments from the orderingArray 15 | for (let i = orderingArray.length - 1; i >= 0; i--) { 16 | if (!orderingArray[i]) orderingArray.splice(i, 1); 17 | } 18 | 19 | this.push(...res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/table/definitions/row-types.spec.ts: -------------------------------------------------------------------------------- 1 | import RowTypes from './row-types'; 2 | 3 | describe('Row Types', () => { 4 | it('Check Is defined', () => { 5 | expect(RowTypes.isDefined(100)).toBe(false); 6 | expect(RowTypes.isDefined(RowTypes.Label)).toBe(true); 7 | expect(RowTypes.isDefined(RowTypes.Filter)).toBe(true); 8 | expect(RowTypes.isDefined(RowTypes.Data)).toBe(true); 9 | }); 10 | it('Check If Row Is Table Head', () => { 11 | expect(RowTypes.isTHead(RowTypes.Label)).toBe(true); 12 | expect(RowTypes.isTHead(RowTypes.Filter)).toBe(true); 13 | expect(RowTypes.isTHead(RowTypes.Data)).toBe(false); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/table/definitions/row-types.ts: -------------------------------------------------------------------------------- 1 | enum RowTypes { 2 | Label = 0, 3 | Filter = 1, 4 | Data = 2, 5 | } 6 | 7 | namespace RowTypes { 8 | export const headerRows: RowTypes[] = [RowTypes.Label, RowTypes.Filter]; 9 | 10 | export function isDefined(rowType: number): boolean { 11 | return Object.values(RowTypes).includes(rowType); 12 | } 13 | 14 | export function isTHead(rowType: RowTypes): boolean { return RowTypes.headerRows.includes(rowType); } 15 | } 16 | 17 | Object.freeze(RowTypes); 18 | export default RowTypes; 19 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/table/tbody-generic.vue: -------------------------------------------------------------------------------- 1 | 17 | 38 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/util/get-object-from-path.spec.ts: -------------------------------------------------------------------------------- 1 | import getObjectFromPath from './get-object-from-path'; 2 | 3 | describe('getObjectFromPath', () => { 4 | beforeEach(() => { 5 | // Mocking the global window object 6 | // Note: Only adding properties needed for the test 7 | (global as any).window = { 8 | property1: { nestedProperty: 'nested value' }, 9 | property2: 'value2', 10 | }; 11 | }); 12 | 13 | afterEach(() => { 14 | // Reset the global window object after each test 15 | delete (global as any).window; 16 | }); 17 | 18 | it('returns the correct value when path is valid', () => { 19 | expect(getObjectFromPath('property1.nestedProperty')).toBe('nested value'); 20 | expect(getObjectFromPath('property2')).toBe('value2'); 21 | }); 22 | 23 | it('returns an empty object when path does not exist', () => { 24 | const result = getObjectFromPath('property3'); 25 | expect(result).toEqual({}); 26 | expect(Object.keys(result).length).toBe(0); 27 | }); 28 | 29 | it('returns undefined when path is not provided', () => { 30 | expect(getObjectFromPath('')).toBeUndefined(); 31 | expect(getObjectFromPath(null as any)).toBeUndefined(); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/util/get-object-from-path.ts: -------------------------------------------------------------------------------- 1 | export default function getObjectFromPath(path: string) { 2 | if (path) { 3 | return path.split('.').reduce((res: { [key: string]: any }, val: string) => res[val] ?? {}, window); 4 | } 5 | return undefined; 6 | } 7 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/util/index.ts: -------------------------------------------------------------------------------- 1 | export { apiClient, dataWithResponse } from './api-client'; 2 | export * from './translations-mixin'; 3 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/util/loading-indicator.spec.ts: -------------------------------------------------------------------------------- 1 | import { mount } from '@vue/test-utils'; 2 | 3 | import LoadingIndicator from './loading-indicator.vue'; 4 | 5 | describe('LoadingIndicator.vue', () => { 6 | it('renders loading state without progress', () => { 7 | const wrapper = mount(LoadingIndicator, { propsData: { loading: true } }); 8 | 9 | expect(wrapper.find('.lds-ellipsis').exists()).toBe(true); 10 | expect(wrapper.find('.progress').exists()).toBe(false); 11 | }); 12 | 13 | it('renders loading state with progress', () => { 14 | const wrapper = mount(LoadingIndicator, { 15 | propsData: { 16 | loading: true, 17 | progress: 30, 18 | label: 'Loading...', 19 | }, 20 | }); 21 | 22 | expect(wrapper.find('.lds-ellipsis').exists()).toBe(false); 23 | expect(wrapper.find('.progress').exists()).toBe(true); 24 | expect(wrapper.find('.progress-bar').attributes('aria-valuenow')).toBe('30'); 25 | expect(wrapper.find('.progress-bar').text()).toContain('30%'); 26 | }); 27 | 28 | it('does not render if loading prop is false', () => { 29 | const wrapper = mount(LoadingIndicator, { propsData: { loading: false } }); 30 | 31 | expect(wrapper.find('.progress-wrapper').exists()).toBe(false); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/util/translations-mixin.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * translations mixin provides utility functions that gettext will recognise 3 | */ 4 | 5 | type InterpolateData = any[] | Record; 6 | 7 | declare global { 8 | interface Window { 9 | gettext?: (str: string) => string; 10 | interpolate?: (str: string, data: InterpolateData, named: boolean) => string; 11 | } 12 | } 13 | 14 | const gettext = (str: string) => ( 15 | window.gettext ? window.gettext(str) : str 16 | ); 17 | 18 | const interpolate = (str: string, data: Record) => ( 19 | window.interpolate ? 20 | window.interpolate(str, data, true) : 21 | str.replace(/%\(\w+\)s/g, (match) => String(data[match.slice(2, -2)])) 22 | ); 23 | 24 | export function useTranslations() { 25 | return { gettext, interpolate }; 26 | } 27 | 28 | export { gettext, interpolate }; 29 | 30 | export default { 31 | methods: { 32 | gettext(str: string) { return gettext(str); }, 33 | interpolate(str: string, data: { [key: string]: any }) { return interpolate(str, data); }, 34 | }, 35 | }; 36 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/components/vuetify.ts: -------------------------------------------------------------------------------- 1 | import VuetifyActions from './actions/actions-vuetify.vue'; 2 | import VuetifyForm from './form/form-component.vue'; 3 | import VuetifyFormLayout from './form/layout-vuetify.vue'; 4 | import { ModalView, DfDialog } from './modal'; 5 | import VuetifyModal from './modal/modal-api-vuetify.vue'; 6 | import VuetifyTable from './table/table-vuetify.vue'; 7 | import LoadingIndicator from './util/loading-indicator.vue'; 8 | 9 | export { 10 | DfDialog, 11 | LoadingIndicator, 12 | ModalView, 13 | 14 | VuetifyActions as DfActions, 15 | VuetifyForm as DfForm, 16 | VuetifyFormLayout as DfFormLayout, 17 | VuetifyModal as DfModalDialog, 18 | VuetifyTable as DfTable, 19 | }; 20 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '@vue/runtime-core' { 2 | interface ComponentCustomProperties { 3 | gettext: (value: string) => string; 4 | interpolate: (str: string, data: { [key: string]: any }) => string; 5 | } 6 | } 7 | 8 | export {}; 9 | -------------------------------------------------------------------------------- /vue/dynamicforms/src/vuetify-components.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/extensions */ 2 | 3 | export { VAlert } from 'vuetify/components/VAlert'; 4 | export { VBtn } from 'vuetify/components/VBtn'; 5 | export { VCard, VCardTitle, VCardText, VCardActions } from 'vuetify/components/VCard'; 6 | export { VCheckbox } from 'vuetify/components/VCheckbox'; 7 | export { VColorPicker } from 'vuetify/components/VColorPicker'; 8 | export { VDialog } from 'vuetify/components/VDialog'; 9 | export { VContainer, VRow, VCol, VSpacer } from 'vuetify/components/VGrid'; 10 | export { VFileInput } from 'vuetify/components/VFileInput'; 11 | export { VInput } from 'vuetify/components/VInput'; 12 | export { VLayout } from 'vuetify/components/VLayout'; 13 | export { VList, VListItem, VListItemTitle } from 'vuetify/components/VList'; 14 | export { VMain } from 'vuetify/components/VMain'; 15 | export { VMenu } from 'vuetify/components/VMenu'; 16 | export { VProgressLinear } from 'vuetify/components/VProgressLinear'; 17 | export { VProgressCircular } from 'vuetify/components/VProgressCircular'; 18 | export { VTextarea } from 'vuetify/components/VTextarea'; 19 | export { VTextField } from 'vuetify/components/VTextField'; 20 | export { VExpandTransition } from 'vuetify/components/transitions'; 21 | -------------------------------------------------------------------------------- /vue/dynamicforms/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": [ 4 | "coverage", 5 | "dist", 6 | "node_modules", 7 | "./**/*.spec.*" 8 | ], 9 | "compilerOptions": { 10 | "declaration": true, 11 | "declarationMap": true, 12 | "sourceMap": true, 13 | "outDir": "./dist", 14 | "skipLibCheck": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /vue/dynamicforms/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "resolveJsonModule": true, 5 | "paths": { 6 | "@/*": ["./src/components/*"], 7 | "~/*": ["../../node_modules/*"], 8 | } 9 | }, 10 | "include": ["src/**/*", "tests/**/*"], 11 | "exclude": [ 12 | "dist", 13 | "coverage", 14 | "node_modules" 15 | ] 16 | } 17 | --------------------------------------------------------------------------------