From 81c03251122de5acd57272906d26f9f9551054e6 Mon Sep 17 00:00:00 2001 From: Artur Barseghyan Date: Tue, 9 May 2017 20:21:39 +0200 Subject: [PATCH 1/7] prepare 0.11.2 --- CHANGELOG.rst | 10 +++++++-- setup.py | 2 +- src/fobi/__init__.py | 4 ++-- src/fobi/contrib/apps/drf_integration/base.py | 22 +++++++++---------- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 12077732..c1a98244 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -15,8 +15,14 @@ are used for versioning (schema follows below): 0.3.4 to 0.4). - All backwards incompatible changes are mentioned in this document. -0.11 ----- +0.11.2 +------ +2017-05-09 + +- Minor fixes in ``drf_integration`` app. + +0.11.1 +------ 2017-05-08 - Minor fixes in ``decimal`` plugin. diff --git a/setup.py b/setup.py index 2943f508..4a848b78 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ import sys from distutils.version import LooseVersion from setuptools import setup, find_packages -version = '0.11.1' +version = '0.11.2' # *************************************************************************** # ************************** Python version ********************************* diff --git a/src/fobi/__init__.py b/src/fobi/__init__.py index 51961608..31211c82 100644 --- a/src/fobi/__init__.py +++ b/src/fobi/__init__.py @@ -1,6 +1,6 @@ __title__ = 'django-fobi' -__version__ = '0.11.1' -__build__ = 0x00007c +__version__ = '0.11.2' +__build__ = 0x00007d __author__ = 'Artur Barseghyan ' __copyright__ = '2014-2017 Artur Barseghyan' __license__ = 'GPL 2.0/LGPL 2.1' diff --git a/src/fobi/contrib/apps/drf_integration/base.py b/src/fobi/contrib/apps/drf_integration/base.py index a9693034..b72c0acf 100644 --- a/src/fobi/contrib/apps/drf_integration/base.py +++ b/src/fobi/contrib/apps/drf_integration/base.py @@ -232,17 +232,17 @@ def submit_plugin_form_data(form_entry, ) if custom_plugin_cls: custom_plugin = custom_plugin_cls() - updated_serializer = \ - custom_plugin._submit_plugin_form_data( - form_element_plugin=form_element_plugin, - form_entry=form_entry, - request=request, - serializer=serializer, - form_element_entries=form_element_entries, - **kwargs - ) - if updated_serializer: - serializer = updated_serializer + updated_serializer = \ + custom_plugin._submit_plugin_form_data( + form_element_plugin=form_element_plugin, + form_entry=form_entry, + request=request, + serializer=serializer, + form_element_entries=form_element_entries, + **kwargs + ) + if updated_serializer: + serializer = updated_serializer return serializer From 792a8e12217d9ca03011c4295be243bde1a24232 Mon Sep 17 00:00:00 2001 From: Artur Barseghyan Date: Tue, 9 May 2017 20:42:01 +0200 Subject: [PATCH 2/7] add more saved forms --- .gitignore | 1 + examples/saved_forms_in_json_format/change-payment-method.json | 1 + .../change-responsible-party-on-account.json | 1 + examples/saved_forms_in_json_format/otevreny-form.json | 1 + examples/saved_forms_in_json_format/ssi-knee-hip.json | 1 + examples/saved_forms_in_json_format/test-dynamic-values.json | 1 + examples/saved_forms_in_json_format/test-form-wizard.json | 1 + examples/saved_forms_in_json_format/test-private-form.json | 1 + examples/saved_forms_in_json_format/test-sliders.json | 1 + .../saved_forms_in_json_format/testing-interesting-project.json | 1 + 10 files changed, 10 insertions(+) create mode 100755 examples/saved_forms_in_json_format/change-payment-method.json create mode 100755 examples/saved_forms_in_json_format/change-responsible-party-on-account.json create mode 100755 examples/saved_forms_in_json_format/otevreny-form.json create mode 100755 examples/saved_forms_in_json_format/ssi-knee-hip.json create mode 100755 examples/saved_forms_in_json_format/test-dynamic-values.json create mode 100755 examples/saved_forms_in_json_format/test-form-wizard.json create mode 100755 examples/saved_forms_in_json_format/test-private-form.json create mode 100755 examples/saved_forms_in_json_format/test-sliders.json create mode 100755 examples/saved_forms_in_json_format/testing-interesting-project.json diff --git a/.gitignore b/.gitignore index 2359a9bb..beb26fd2 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,7 @@ README_PARTS.rst /examples/media/cache/ /examples/simple/lund_urls.py /examples/simple/lund/ +/examples/saved_forms_in_json_format/all/ /examples/simple/settings/local_settings.py /examples/simple/settings/local_settings_foundation5.py /examples/simple/settings/bootstrap3_theme_django_1_9_lund.py diff --git a/examples/saved_forms_in_json_format/change-payment-method.json b/examples/saved_forms_in_json_format/change-payment-method.json new file mode 100755 index 00000000..8ea6da94 --- /dev/null +++ b/examples/saved_forms_in_json_format/change-payment-method.json @@ -0,0 +1 @@ +{"success_page_message": "", "is_public": false, "success_page_title": "", "slug": "change-payment-method", "form_handlers": [], "action": "", "name": "Change Payment Method", "is_cloneable": false, "form_elements": [{"plugin_data": "{\"required\": false, \"name\": \"customer_id\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"Customer ID\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 1}, {"plugin_data": "{\"required\": false, \"name\": \"account_hold_name\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"Account Hold Name\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 2}, {"plugin_data": "{\"required\": false, \"name\": \"account_password\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"Account Password\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 3}, {"plugin_data": "{\"required\": false, \"name\": \"contact_phone_number\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"Contact Phone Number\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 4}, {"plugin_data": "{\"required\": false, \"name\": \"contact_email_address\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"Contact email address\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 5}, {"plugin_data": "{\"required\": false, \"name\": \"new_payment_method\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"New Payment Method\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 6}, {"plugin_data": "{\"required\": false, \"name\": \"card_holder_or_account_holder\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"Card Holder or Account Holder\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 7}, {"plugin_data": "{\"required\": false, \"name\": \"account_number\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"Account Number\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 8}, {"plugin_data": "{\"required\": false, \"name\": \"routing_code_if_electronic_check\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"Routing Code (if electronic check)\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 9}, {"plugin_data": "{\"required\": false, \"name\": \"expiration_date_if_card\", \"help_text\": \"\", \"label\": \"Expiration date if Card\", \"input_formats\": \"\", \"initial\": null}", "plugin_uid": "date", "position": 10}, {"plugin_data": "{\"required\": false, \"name\": \"cvv_if_card\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"CVV if Card\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 11}]} \ No newline at end of file diff --git a/examples/saved_forms_in_json_format/change-responsible-party-on-account.json b/examples/saved_forms_in_json_format/change-responsible-party-on-account.json new file mode 100755 index 00000000..8129a7a6 --- /dev/null +++ b/examples/saved_forms_in_json_format/change-responsible-party-on-account.json @@ -0,0 +1 @@ +{"success_page_message": "", "is_public": false, "success_page_title": "", "slug": "change-responsible-party-on-account", "form_handlers": [], "action": "", "name": "Change Responsible Party on Account", "is_cloneable": false, "form_elements": [{"plugin_data": "{\"required\": true, \"name\": \"customer_id\", \"help_text\": \"\", \"max_length\": 8, \"label\": \"Customer ID\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 1}, {"plugin_data": "{\"required\": true, \"name\": \"name\", \"help_text\": \"\", \"max_length\": 50, \"label\": \"Account Hold Name\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 2}, {"plugin_data": "{\"required\": false, \"name\": \"new_user_first_name\", \"help_text\": \"\", \"max_length\": 50, \"label\": \"New User First Name\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 3}, {"plugin_data": "{\"required\": false, \"name\": \"new_user_last_name\", \"help_text\": \"\", \"max_length\": 50, \"label\": \"New User Last Name\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 4}, {"plugin_data": "{\"required\": false, \"name\": \"relationship_to_account_holder_if_any\", \"help_text\": \"\", \"max_length\": 50, \"label\": \"Relationship to Account Holder, if Any\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 5}, {"plugin_data": "{\"required\": false, \"name\": \"account_password\", \"help_text\": \"\", \"max_length\": 50, \"label\": \"Account Password\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 6}, {"plugin_data": "{\"required\": false, \"name\": \"contact_phone_number\", \"help_text\": \"\", \"max_length\": 50, \"label\": \"Contact Phone Number\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 7}, {"plugin_data": "{\"required\": false, \"name\": \"contact_email_address\", \"help_text\": \"\", \"max_length\": 50, \"label\": \"Contact email address\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 8}, {"plugin_data": "{\"required\": false, \"choices\": \"1, Electronic Check\\r\\n2, Visa \\r\\n3, Mastercard \\r\\n4, American Express, \\r\\n5, Discover\", \"name\": \"new_payment_method\", \"help_text\": \"\", \"label\": \"New Payment Method\", \"initial\": \"\"}", "plugin_uid": "select", "position": 9}, {"plugin_data": "{\"required\": false, \"name\": \"account_number\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"Account Number\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 10}, {"plugin_data": "{\"required\": false, \"name\": \"routing_code_if_electronic_check\", \"help_text\": \"\", \"max_length\": 50, \"label\": \"Routing Code (if electronic check)\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 11}, {"plugin_data": "{\"required\": false, \"name\": \"expiration_date_if_card\", \"help_text\": \"\", \"label\": \"Expiration date if Card\", \"input_formats\": \"\", \"initial\": null}", "plugin_uid": "date", "position": 12}, {"plugin_data": "{\"required\": false, \"name\": \"cvv_if_card\", \"help_text\": \"\", \"max_length\": 8, \"label\": \"CVV if Card\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 13}]} \ No newline at end of file diff --git a/examples/saved_forms_in_json_format/otevreny-form.json b/examples/saved_forms_in_json_format/otevreny-form.json new file mode 100755 index 00000000..73845562 --- /dev/null +++ b/examples/saved_forms_in_json_format/otevreny-form.json @@ -0,0 +1 @@ +{"name": "Otevreny form (imported on 2016-11-30 21:33:48)", "is_public": false, "form_handlers": [], "form_elements": [{"position": 1, "plugin_uid": "text", "plugin_data": "{\"name\": \"jmeno\", \"max_length\": 80, \"required\": true, \"label\": \"Jm\\u00e9no\", \"help_text\": \"Zadejte sv\\u00e9 jm\\u00e9no\", \"initial\": \"\", \"placeholder\": \"Jm\\u00e9no\"}"}, {"position": 2, "plugin_uid": "text", "plugin_data": "{\"name\": \"prijmeni\", \"max_length\": 255, \"required\": true, \"label\": \"P\\u0159\\u00edjmen\\u00ed\", \"help_text\": \"Zadejte sv\\u00e9 p\\u0159\\u00edjmen\\u00ed\", \"initial\": \"\", \"placeholder\": \"P\\u0159\\u00edjmen\\u00ed\"}"}, {"position": 3, "plugin_uid": "text", "plugin_data": "{\"name\": \"prezdivka\", \"max_length\": 255, \"required\": false, \"label\": \"P\\u0159ezd\\u00edvka\", \"help_text\": \"Zadejte svoji p\\u0159ezd\\u00edvku\", \"initial\": \"\", \"placeholder\": \"P\\u0159ezd\\u00edvka\"}"}, {"position": 4, "plugin_uid": "email", "plugin_data": "{\"name\": \"e_mail\", \"max_length\": 255, \"required\": true, \"label\": \"E-mail\", \"help_text\": \"Zadejte sv\\u016fj e-mail\", \"initial\": \"\", \"placeholder\": \"E-mail\"}"}, {"position": 5, "plugin_uid": "date_drop_down", "plugin_data": "{\"input_formats\": \"\", \"name\": \"datum_narozeni\", \"year_max\": 2050, \"label\": \"Datum narozen\\u00ed\", \"year_min\": 1950, \"help_text\": \"Zadejte sv\\u00e9 datum narozen\\u00ed.\", \"initial\": \"2000\", \"required\": true}"}, {"position": 6, "plugin_uid": "textarea", "plugin_data": "{\"name\": \"dalsi_informace_o_soutezicim\", \"required\": true, \"label\": \"Dal\\u0161\\u00ed informace o sout\\u011b\\u017e\\u00edc\\u00edm\", \"help_text\": \"Z\\u00e1jmy a tak\", \"initial\": \"\", \"placeholder\": \"\"}"}], "slug": "otevreny-form", "success_page_title": "Success page title", "success_page_message": "Success page body", "is_cloneable": false, "action": ""} \ No newline at end of file diff --git a/examples/saved_forms_in_json_format/ssi-knee-hip.json b/examples/saved_forms_in_json_format/ssi-knee-hip.json new file mode 100755 index 00000000..9569a78d --- /dev/null +++ b/examples/saved_forms_in_json_format/ssi-knee-hip.json @@ -0,0 +1 @@ +{"name": "SSI Knee & Hip", "form_elements": [{"plugin_data": "{\"required\": true, \"initial\": \"\", \"placeholder\": \"\", \"help_text\": \"\", \"max_length\": 255, \"name\": \"surgeon\", \"label\": \"Surgeon\"}", "plugin_uid": "text", "position": 1}, {"plugin_data": "{\"required\": true, \"initial\": null, \"name\": \"hospital_number\", \"help_text\": \"\", \"max_value\": null, \"min_value\": null, \"placeholder\": \"\", \"label\": \"Hospital number\"}", "plugin_uid": "integer", "position": 2}, {"plugin_data": "{\"required\": true, \"initial\": \"\", \"placeholder\": \"\", \"help_text\": \"\", \"max_length\": 255, \"name\": \"anaesthetist\", \"label\": \"Anaesthetist\"}", "plugin_uid": "text", "position": 3}, {"plugin_data": "{\"choices\": \"Ward 1\\r\\nWard 2\\r\\nWard 3\\r\\nWard 4\\r\\nWard 5\\r\\nWard 6\", \"initial\": \"\", \"help_text\": \"Select\", \"label\": \"Ward\", \"name\": \"ward\", \"required\": true}", "plugin_uid": "select", "position": 4}, {"plugin_data": "{\"label\": \"Gender\", \"initial\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"gender\", \"choices\": \"Male\\r\\nFemale\"}", "plugin_uid": "radio", "position": 5}, {"plugin_data": "{\"label\": \"Age\", \"initial\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"age\", \"choices\": \"<50\\r\\n51-71\\r\\n71+\"}", "plugin_uid": "radio", "position": 6}, {"plugin_data": "{\"choices\": \"Osteoarthritis \\r\\nInflammatory Joint Disease\\r\\nOther\", \"initial\": \"\", \"help_text\": \"Select\", \"label\": \"Diagnosis\", \"name\": \"diagnosis\", \"required\": true}", "plugin_uid": "select", "position": 7}, {"plugin_data": "{\"label\": \"Diabetic\", \"initial\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"diabetic\", \"choices\": \"Yes\\r\\nNo\"}", "plugin_uid": "radio", "position": 8}, {"plugin_data": "{\"label\": \"ASA score\", \"initial\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"asa_score\", \"choices\": \"1\\r\\n2\\r\\n3\"}", "plugin_uid": "radio", "position": 9}, {"plugin_data": "{\"label\": \"MRSA\", \"initial\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"mrsa\", \"choices\": \"Yes\\r\\nNo\\r\\nPositive\"}", "plugin_uid": "radio", "position": 10}, {"plugin_data": "{\"label\": \"MSU screen pre-op\", \"initial\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"msu_screen_pre_op\", \"choices\": \"Yes\\r\\nNo\\r\\nPositive\"}", "plugin_uid": "radio", "position": 11}, {"plugin_data": "{\"label\": \"Was patient admitted due to SSI\", \"initial\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"was_patient_admitted_due_to_ssi\", \"choices\": \"Yes\\r\\nNo\"}", "plugin_uid": "radio", "position": 12}, {"plugin_data": "{\"label\": \"Has patient been on steroids >7 days prior to surgery\", \"initial\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"has_patient_been_on_steroids_7_days_prior_to_surgery\", \"choices\": \"Yes\\r\\nNo\"}", "plugin_uid": "radio", "position": 13}, {"plugin_data": "{\"initial\": null, \"input_formats\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"date_of_admission\", \"label\": \"Date of Admission\"}", "plugin_uid": "date", "position": 14}, {"plugin_data": "{\"initial\": null, \"input_formats\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"date_of_procedure_antibiotic_administration_date\", \"label\": \"Date of procedure/ antibiotic administration date\"}", "plugin_uid": "date", "position": 15}, {"plugin_data": "{\"initial\": null, \"input_formats\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"anaesthetic_start_time\", \"label\": \"Anaesthetic start time\"}", "plugin_uid": "datetime", "position": 16}, {"plugin_data": "{\"initial\": null, \"input_formats\": \"\", \"help_text\": \"\", \"required\": false, \"name\": \"antibiotic_administration_time\", \"label\": \"Antibiotic administration time\"}", "plugin_uid": "datetime", "position": 17}, {"plugin_data": "{\"required\": false, \"initial\": \"\", \"placeholder\": \"Type here\", \"help_text\": \"\", \"max_length\": 255, \"name\": \"antibiotic_administration_route\", \"label\": \"Antibiotic administration route\"}", "plugin_uid": "text", "position": 18}, {"plugin_data": "{\"label\": \"Time of IV AB's administration\", \"initial\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"time_of_iv_abs_administration\", \"choices\": \"Within 1 hour prior to incision\\r\\nAt surgical incision time\\r\\nNot documented\\r\\nAnaesthetic end time\"}", "plugin_uid": "select", "position": 19}, {"plugin_data": "{\"label\": \"Type of antibiotic\", \"initial\": \"\", \"help_text\": \"\", \"required\": false, \"name\": \"type_of_antibiotic\", \"choices\": \"Zinacef\\r\\nVancomycin\\r\\nOther\\r\\nAntibiotic allergy\"}", "plugin_uid": "select", "position": 20}, {"plugin_data": "{\"choices\": \"Stopped within 24\\u00b0 of anaesthesia end time\\r\\nStopped within 48\\u00b0 of anaesthesia end time\\r\\n> 48\\u00b0\\r\\n> ?\\r\\nUTI?\\r\\nRTI?\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Length of time IV AB's continued\", \"name\": \"length_of_time_iv_abs_continued\", \"required\": true}", "plugin_uid": "select", "position": 21}, {"plugin_data": "{\"choices\": \"<4 (or=??)\\r\\n>4\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Number of doses\", \"name\": \"number_of_doses\", \"required\": false}", "plugin_uid": "radio", "position": 22}, {"plugin_data": "{\"choices\": \" 72 hours\\r\\nRemoval not documented\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"IV cannula removal\", \"name\": \"iv_cannula_removal\", \"required\": false}", "plugin_uid": "select", "position": 23}, {"plugin_data": "{\"choices\": \"Yes\\r\\nNo\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Catheterised intra op\", \"name\": \"catheterised_intra_op\", \"required\": false}", "plugin_uid": "radio", "position": 24}, {"plugin_data": "{\"choices\": \"Yes\\r\\nNo\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Was pt catheterised within 24\\u00b0 post operatively\", \"name\": \"was_pt_catheterised_within_24_post_operatively\", \"required\": false}", "plugin_uid": "radio", "position": 25}, {"plugin_data": "{\"choices\": \"General\\r\\nRegional\\r\\nBoth\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Type of anaesthetic\", \"name\": \"type_of_anaesthetic\", \"required\": false}", "plugin_uid": "radio", "position": 26}, {"plugin_data": "{\"choices\": \"Pre admission warfare\\r\\nLow molecular heparin - Innohep or cleaner\\r\\nWarfarin\\r\\nOral factor - Xarelto\\r\\nNu-Seals aspirin\\r\\n?? Reason, cells alva get, timeout, blood transfusion??\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"VTE prophylaxis\", \"name\": \"vte_prophylaxis\", \"required\": false}", "plugin_uid": "select_multiple", "position": 27}, {"plugin_data": "{\"choices\": \"Intrathecal morphine\\r\\nFemoral block\\r\\nPCA\\r\\nIM/PO\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Post op pain management\", \"name\": \"post_op_pain_management\", \"required\": false}", "plugin_uid": "select", "position": 28}, {"plugin_data": "{\"choices\": \"Yes\\r\\nNo\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"VTE prophylaxis started within 24 hours of surgery\", \"name\": \"vte_prophylaxis_started_within_24_hours_of_surgery\", \"required\": false}", "plugin_uid": "radio", "position": 29}, {"plugin_data": "{\"choices\": \"<500\\r\\n500-750\\r\\n750+\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Blood loss\", \"name\": \"blood_loss\", \"required\": false}", "plugin_uid": "select", "position": 30}, {"plugin_data": "{\"choices\": \"Op-site 10 X 30\\r\\nMepore 10 X 30\\r\\nJubilee\\r\\nOther\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Type of primary dressing\", \"name\": \"type_of_primary_dressing\", \"required\": false}", "plugin_uid": "select", "position": 31}, {"plugin_data": "{\"choices\": \"1\\r\\n2\\r\\n3\\r\\n4\\r\\n5\\r\\n6+\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Number of dressing changes\", \"name\": \"number_of_dressing_changes\", \"required\": false}", "plugin_uid": "radio", "position": 32}, {"plugin_data": "{\"choices\": \"Clean\\r\\nClean contaminated\\r\\nContaminated\\r\\nDirty or infected\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Wound class\", \"name\": \"wound_class\", \"required\": false}", "plugin_uid": "select", "position": 33}, {"plugin_data": "{\"choices\": \"Yes (if yes, number of doses)\\r\\nNo\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Innapropriate administration of perfalgan\", \"name\": \"innapropriate_administration_of_perfalgan\", \"required\": false}", "plugin_uid": "radio", "position": 34}, {"plugin_data": "{\"choices\": \"Yes\\r\\nNo\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Day 5 SSI nursing documentation completed\", \"name\": \"day_5_ssi_nursing_documentation_completed\", \"required\": false}", "plugin_uid": "radio", "position": 35}, {"plugin_data": "{\"choices\": \"Yes\\r\\nNo\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"D/C SSI nursing documentation completed\", \"name\": \"dc_ssi_nursing_documentation_completed\", \"required\": false}", "plugin_uid": "radio", "position": 36}, {"plugin_data": "{\"choices\": \"<= 5 days\\r\\n6-10 days\\r\\n11-15 days\\r\\n16+ days\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Length of stay\", \"name\": \"length_of_stay\", \"required\": false}", "plugin_uid": "select", "position": 37}, {"plugin_data": "{\"initial\": \"\", \"help_text\": \"\", \"label\": \"Comment?\", \"required\": false, \"name\": \"comment\", \"placeholder\": \"\", \"max_length\": 255}", "plugin_uid": "text", "position": 38}, {"plugin_data": "{\"choices\": \"Yes\\r\\nNo\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Has patient developed an SSI\", \"name\": \"has_patient_developed_an_ssi\", \"required\": false}", "plugin_uid": "radio", "position": 39}, {"plugin_data": "{\"choices\": \"Superficial incisional\\r\\nDeep incisional\\r\\nOrgan space\\r\\n\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Type of SSI\", \"name\": \"type_of_ssi\", \"required\": false}", "plugin_uid": "select", "position": 40}, {"plugin_data": "{\"choices\": \"Joint of Bursa\\r\\nOsteomyelitis\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Site of organ / space infection\", \"name\": \"site_of_organ_space_infection\", \"required\": false}", "plugin_uid": "select", "position": 41}, {"plugin_data": "{\"choices\": \"Yes\\r\\nNo\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Returned to theatre for drainage of abscess/ washout\", \"name\": \"returned_to_theatre_for_drainage_of_abscess_washout\", \"required\": false}", "plugin_uid": "radio", "position": 42}, {"plugin_data": "{\"choices\": \"During hospital stay\\r\\nOn readmission\\r\\nPost discharge\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"When was surgical site infection detected\", \"name\": \"when_was_surgical_site_infection_detected\", \"required\": false}", "plugin_uid": "select", "position": 43}, {"plugin_data": "{\"choices\": \"Home\\r\\nRelative\\r\\nNursing home\\r\\nOther\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Discharged to\", \"name\": \"discharged_to\", \"required\": false}", "plugin_uid": "select", "position": 44}, {"plugin_data": "{\"text\": \"Blood cultures\"}", "plugin_uid": "content_text", "position": 45}, {"plugin_data": "{\"initial\": null, \"input_formats\": \"\", \"label\": \"Date sent\", \"name\": \"date_sent\", \"help_text\": \"\", \"required\": false}", "plugin_uid": "date", "position": 46}, {"plugin_data": "{\"choices\": \"Yes\\r\\nNo\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Contaminated specimen\", \"name\": \"contaminated_specimen\", \"required\": false}", "plugin_uid": "radio", "position": 47}, {"plugin_data": "{\"initial\": \"\", \"help_text\": \"\", \"label\": \"Growth\", \"required\": false, \"name\": \"growth\", \"placeholder\": \"\", \"max_length\": 255}", "plugin_uid": "text", "position": 48}, {"plugin_data": "{\"initial\": \"\", \"help_text\": \"\", \"label\": \"Sensitivity\", \"required\": false, \"name\": \"sensitivity\", \"placeholder\": \"\", \"max_length\": 255}", "plugin_uid": "text", "position": 49}], "action": "", "is_public": false, "is_cloneable": false, "slug": "ssi-knee-hip", "position": null, "form_handlers": [{"plugin_data": null, "plugin_uid": "db_store"}, {"plugin_data": "{\"subject\": \"SSI Knee & Hip form\", \"body\": \"SSI Knee & Hip form submitted\", \"from_name\": \"Someone\", \"to_name\": \"Someone\", \"from_email\": \"foreverchild.to@gmail.com\", \"to_email\": [\"foreverchild.to@gmail.com\"]}", "plugin_uid": "mail"}], "success_page_title": "Form submitted successfully", "success_page_message": ""} \ No newline at end of file diff --git a/examples/saved_forms_in_json_format/test-dynamic-values.json b/examples/saved_forms_in_json_format/test-dynamic-values.json new file mode 100755 index 00000000..3f10a987 --- /dev/null +++ b/examples/saved_forms_in_json_format/test-dynamic-values.json @@ -0,0 +1 @@ +{"form_handlers": [{"plugin_data": null, "plugin_uid": "db_store"}], "name": "Test dynamic values", "action": "", "success_page_message": "", "slug": "test-dynamic-values", "success_page_title": "", "form_elements": [{"plugin_data": "{\"name\": \"username\", \"required\": false, \"help_text\": \"\", \"placeholder\": \"\", \"initial\": \"{{ request.user.get_username }}\", \"max_length\": 255, \"label\": \"Username\"}", "plugin_uid": "text", "position": 136}, {"plugin_data": "{\"name\": \"origin\", \"required\": false, \"help_text\": \"\", \"placeholder\": \"\", \"initial\": \"{{ request.path }}\", \"max_length\": 255, \"label\": \"Origin\"}", "plugin_uid": "text", "position": 137}, {"plugin_data": "{\"name\": \"meta\", \"required\": false, \"help_text\": \"\", \"placeholder\": \"\", \"initial\": \"{{ request.META }}\", \"label\": \"Meta\"}", "plugin_uid": "textarea", "position": 138}, {"plugin_data": "{\"placeholder\": \"\", \"name\": \"test_if_it_breaks\", \"label\": \"Test if it breaks\", \"required\": false, \"help_text\": \"\", \"initial\": \"{% load admin_list %}{% admin_actions %}\\r\\n{{ request.user.get_username }}\\r\\n{{ request.user.email }}\\r\\n{{ request.path }}\\r\\n{{ request.META }}\\r\\n\"}", "plugin_uid": "textarea", "position": 161}], "is_public": false, "is_cloneable": false, "position": null} \ No newline at end of file diff --git a/examples/saved_forms_in_json_format/test-form-wizard.json b/examples/saved_forms_in_json_format/test-form-wizard.json new file mode 100755 index 00000000..7e50c235 --- /dev/null +++ b/examples/saved_forms_in_json_format/test-form-wizard.json @@ -0,0 +1 @@ +{"name": "Hospital survey", "is_cloneable": false, "form_wizard_forms": [{"action": "", "name": "Hospital Forms", "is_cloneable": false, "form_elements": [{"plugin_uid": "select", "position": 1, "plugin_data": "{\"name\": \"staff_type\", \"label\": \"Staff Type\", \"required\": true, \"choices\": \"\\r\\nNurse\\r\\nDoctor\\r\\nNCHD\\r\\nPorter\\r\\nMidWife\", \"help_text\": \"\", \"initial\": \"\"}"}, {"plugin_uid": "text", "position": 2, "plugin_data": "{\"name\": \"ward_name\", \"placeholder\": \"\", \"label\": \"Ward Name\", \"required\": true, \"max_length\": 255, \"help_text\": \"Choose ward\", \"initial\": \"\"}"}, {"plugin_uid": "honeypot", "position": 4, "plugin_data": "{\"label\": \"Test Field\", \"name\": \"test_field\", \"max_length\": 255, \"required\": true, \"initial\": \"Test item\"}"}, {"plugin_uid": "select_multiple", "position": 5, "plugin_data": "{\"name\": \"barrier_to_correct_technique\", \"label\": \"Barrier to correct technique\", \"required\": false, \"choices\": \"Sleeves to wrist\\r\\nRings\\r\\nDirty nails\\r\\n\", \"help_text\": \"Help text\", \"initial\": \"\"}"}, {"plugin_uid": "select", "position": 6, "plugin_data": "{\"name\": \"correct_technique\", \"label\": \"Correct technique\", \"required\": false, \"choices\": \"Yes\\r\\nNo\\r\\nNot applicable\", \"help_text\": \"\", \"initial\": \"\"}"}, {"plugin_uid": "boolean", "position": 7, "plugin_data": "{\"label\": \"Is this a new entry?\", \"initial\": true, \"name\": \"is_this_a_new_entry\", \"help_text\": \"\", \"required\": false}"}, {"plugin_uid": "boolean", "position": 8, "plugin_data": "{\"label\": \"Check this box to continue\", \"initial\": false, \"name\": \"check_this_box_to_continue\", \"help_text\": \"\", \"required\": true}"}], "success_page_title": "Congrats your form is complete", "slug": "hospital-forms", "form_handlers": [{"plugin_uid": "http_repost", "plugin_data": "{\"endpoint_url\": \"https://django-fobi.herokuapp.com/en/fobi/forms/handlers/add/584/http_repost/\"}"}, {"plugin_uid": "db_store", "plugin_data": null}], "success_page_message": "You passed", "is_public": false}, {"action": "", "name": "SSI Knee & Hip", "is_cloneable": false, "form_elements": [{"plugin_uid": "integer", "position": 209, "plugin_data": "{\"required\": true, \"initial\": null, \"name\": \"hospital_number\", \"help_text\": \"\", \"max_value\": null, \"min_value\": null, \"placeholder\": \"\", \"label\": \"Hospital number\"}"}, {"plugin_uid": "text", "position": 210, "plugin_data": "{\"required\": true, \"initial\": \"\", \"placeholder\": \"\", \"help_text\": \"\", \"max_length\": 255, \"name\": \"surgeon\", \"label\": \"Surgeon\"}"}, {"plugin_uid": "text", "position": 211, "plugin_data": "{\"required\": true, \"initial\": \"\", \"placeholder\": \"\", \"help_text\": \"\", \"max_length\": 255, \"name\": \"anaesthetist\", \"label\": \"Anaesthetist\"}"}, {"plugin_uid": "select", "position": 212, "plugin_data": "{\"choices\": \"Ward 1\\r\\nWard 2\\r\\nWard 3\\r\\nWard 4\\r\\nWard 5\\r\\nWard 6\", \"initial\": \"\", \"help_text\": \"Select\", \"label\": \"Ward\", \"name\": \"ward\", \"required\": true}"}, {"plugin_uid": "radio", "position": 213, "plugin_data": "{\"label\": \"Gender\", \"initial\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"gender\", \"choices\": \"Male\\r\\nFemale\"}"}, {"plugin_uid": "radio", "position": 214, "plugin_data": "{\"label\": \"Age\", \"initial\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"age\", \"choices\": \"<50\\r\\n51-71\\r\\n71+\"}"}, {"plugin_uid": "select", "position": 215, "plugin_data": "{\"choices\": \"Osteoarthritis \\r\\nInflammatory Joint Disease\\r\\nOther\", \"initial\": \"\", \"help_text\": \"Select\", \"label\": \"Diagnosis\", \"name\": \"diagnosis\", \"required\": true}"}, {"plugin_uid": "radio", "position": 216, "plugin_data": "{\"label\": \"Diabetic\", \"initial\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"diabetic\", \"choices\": \"Yes\\r\\nNo\"}"}, {"plugin_uid": "radio", "position": 217, "plugin_data": "{\"label\": \"ASA score\", \"initial\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"asa_score\", \"choices\": \"1\\r\\n2\\r\\n3\"}"}, {"plugin_uid": "radio", "position": 218, "plugin_data": "{\"label\": \"MRSA\", \"initial\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"mrsa\", \"choices\": \"Yes\\r\\nNo\\r\\nPositive\"}"}, {"plugin_uid": "radio", "position": 219, "plugin_data": "{\"label\": \"MSU screen pre-op\", \"initial\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"msu_screen_pre_op\", \"choices\": \"Yes\\r\\nNo\\r\\nPositive\"}"}, {"plugin_uid": "radio", "position": 220, "plugin_data": "{\"label\": \"Was patient admitted due to SSI\", \"initial\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"was_patient_admitted_due_to_ssi\", \"choices\": \"Yes\\r\\nNo\"}"}, {"plugin_uid": "radio", "position": 221, "plugin_data": "{\"label\": \"Has patient been on steroids >7 days prior to surgery\", \"initial\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"has_patient_been_on_steroids_7_days_prior_to_surgery\", \"choices\": \"Yes\\r\\nNo\"}"}, {"plugin_uid": "date", "position": 222, "plugin_data": "{\"initial\": null, \"input_formats\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"date_of_admission\", \"label\": \"Date of Admission\"}"}, {"plugin_uid": "date", "position": 223, "plugin_data": "{\"initial\": null, \"input_formats\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"date_of_procedure_antibiotic_administration_date\", \"label\": \"Date of procedure/ antibiotic administration date\"}"}, {"plugin_uid": "datetime", "position": 224, "plugin_data": "{\"initial\": null, \"input_formats\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"anaesthetic_start_time\", \"label\": \"Anaesthetic start time\"}"}, {"plugin_uid": "datetime", "position": 225, "plugin_data": "{\"initial\": null, \"input_formats\": \"\", \"help_text\": \"\", \"required\": false, \"name\": \"antibiotic_administration_time\", \"label\": \"Antibiotic administration time\"}"}, {"plugin_uid": "text", "position": 226, "plugin_data": "{\"required\": false, \"initial\": \"\", \"placeholder\": \"Type here\", \"help_text\": \"\", \"max_length\": 255, \"name\": \"antibiotic_administration_route\", \"label\": \"Antibiotic administration route\"}"}, {"plugin_uid": "select", "position": 227, "plugin_data": "{\"label\": \"Time of IV AB's administration\", \"initial\": \"\", \"help_text\": \"\", \"required\": true, \"name\": \"time_of_iv_abs_administration\", \"choices\": \"Within 1 hour prior to incision\\r\\nAt surgical incision time\\r\\nNot documented\\r\\nAnaesthetic end time\"}"}, {"plugin_uid": "select", "position": 228, "plugin_data": "{\"label\": \"Type of antibiotic\", \"initial\": \"\", \"help_text\": \"\", \"required\": false, \"name\": \"type_of_antibiotic\", \"choices\": \"Zinacef\\r\\nVancomycin\\r\\nOther\\r\\nAntibiotic allergy\"}"}, {"plugin_uid": "select", "position": 229, "plugin_data": "{\"choices\": \"Stopped within 24\\u00b0 of anaesthesia end time\\r\\nStopped within 48\\u00b0 of anaesthesia end time\\r\\n> 48\\u00b0\\r\\n> ?\\r\\nUTI?\\r\\nRTI?\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Length of time IV AB's continued\", \"name\": \"length_of_time_iv_abs_continued\", \"required\": true}"}, {"plugin_uid": "radio", "position": 230, "plugin_data": "{\"choices\": \"<4 (or=??)\\r\\n>4\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Number of doses\", \"name\": \"number_of_doses\", \"required\": false}"}, {"plugin_uid": "select", "position": 231, "plugin_data": "{\"choices\": \" 72 hours\\r\\nRemoval not documented\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"IV cannula removal\", \"name\": \"iv_cannula_removal\", \"required\": false}"}, {"plugin_uid": "radio", "position": 232, "plugin_data": "{\"choices\": \"Yes\\r\\nNo\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Catheterised intra op\", \"name\": \"catheterised_intra_op\", \"required\": false}"}, {"plugin_uid": "radio", "position": 233, "plugin_data": "{\"choices\": \"Yes\\r\\nNo\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Was pt catheterised within 24\\u00b0 post operatively\", \"name\": \"was_pt_catheterised_within_24_post_operatively\", \"required\": false}"}, {"plugin_uid": "radio", "position": 234, "plugin_data": "{\"choices\": \"General\\r\\nRegional\\r\\nBoth\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Type of anaesthetic\", \"name\": \"type_of_anaesthetic\", \"required\": false}"}, {"plugin_uid": "select", "position": 235, "plugin_data": "{\"choices\": \"Intrathecal morphine\\r\\nFemoral block\\r\\nPCA\\r\\nIM/PO\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Post op pain management\", \"name\": \"post_op_pain_management\", \"required\": false}"}, {"plugin_uid": "radio", "position": 236, "plugin_data": "{\"choices\": \"Yes\\r\\nNo\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"VTE prophylaxis started within 24 hours of surgery\", \"name\": \"vte_prophylaxis_started_within_24_hours_of_surgery\", \"required\": false}"}, {"plugin_uid": "select", "position": 237, "plugin_data": "{\"choices\": \"<500\\r\\n500-750\\r\\n750+\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Blood loss\", \"name\": \"blood_loss\", \"required\": false}"}, {"plugin_uid": "select_multiple", "position": 238, "plugin_data": "{\"required\": false, \"name\": \"vte_prophylaxis\", \"initial\": \"\", \"label\": \"VTE prophylaxis\", \"help_text\": \"\", \"choices\": \"Pre admission warfare\\r\\nLow molecular heparin - Innohep or cleaner\\r\\nWarfarin\\r\\nOral factor - Xarelto\\r\\nNu-Seals aspirin\\r\\n?? Reason, cells alva get, timeout, blood transfusion??\"}"}, {"plugin_uid": "select", "position": 239, "plugin_data": "{\"choices\": \"Op-site 10 X 30\\r\\nMepore 10 X 30\\r\\nJubilee\\r\\nOther\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Type of primary dressing\", \"name\": \"type_of_primary_dressing\", \"required\": false}"}, {"plugin_uid": "radio", "position": 240, "plugin_data": "{\"choices\": \"1\\r\\n2\\r\\n3\\r\\n4\\r\\n5\\r\\n6+\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Number of dressing changes\", \"name\": \"number_of_dressing_changes\", \"required\": false}"}, {"plugin_uid": "select", "position": 241, "plugin_data": "{\"choices\": \"Clean\\r\\nClean contaminated\\r\\nContaminated\\r\\nDirty or infected\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Wound class\", \"name\": \"wound_class\", \"required\": false}"}, {"plugin_uid": "radio", "position": 242, "plugin_data": "{\"choices\": \"Yes (if yes, number of doses)\\r\\nNo\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Innapropriate administration of perfalgan\", \"name\": \"innapropriate_administration_of_perfalgan\", \"required\": false}"}, {"plugin_uid": "radio", "position": 243, "plugin_data": "{\"choices\": \"Yes\\r\\nNo\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Day 5 SSI nursing documentation completed\", \"name\": \"day_5_ssi_nursing_documentation_completed\", \"required\": false}"}, {"plugin_uid": "radio", "position": 244, "plugin_data": "{\"choices\": \"Yes\\r\\nNo\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"D/C SSI nursing documentation completed\", \"name\": \"dc_ssi_nursing_documentation_completed\", \"required\": false}"}, {"plugin_uid": "select", "position": 245, "plugin_data": "{\"choices\": \"<= 5 days\\r\\n6-10 days\\r\\n11-15 days\\r\\n16+ days\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Length of stay\", \"name\": \"length_of_stay\", \"required\": false}"}, {"plugin_uid": "text", "position": 246, "plugin_data": "{\"initial\": \"\", \"help_text\": \"\", \"label\": \"Comment?\", \"required\": false, \"name\": \"comment\", \"placeholder\": \"\", \"max_length\": 255}"}, {"plugin_uid": "radio", "position": 247, "plugin_data": "{\"choices\": \"Yes\\r\\nNo\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Has patient developed an SSI\", \"name\": \"has_patient_developed_an_ssi\", \"required\": false}"}, {"plugin_uid": "select", "position": 248, "plugin_data": "{\"choices\": \"Superficial incisional\\r\\nDeep incisional\\r\\nOrgan space\\r\\n\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Type of SSI\", \"name\": \"type_of_ssi\", \"required\": false}"}, {"plugin_uid": "select", "position": 249, "plugin_data": "{\"choices\": \"Joint of Bursa\\r\\nOsteomyelitis\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Site of organ / space infection\", \"name\": \"site_of_organ_space_infection\", \"required\": false}"}, {"plugin_uid": "radio", "position": 250, "plugin_data": "{\"choices\": \"Yes\\r\\nNo\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Returned to theatre for drainage of abscess/ washout\", \"name\": \"returned_to_theatre_for_drainage_of_abscess_washout\", \"required\": false}"}, {"plugin_uid": "select", "position": 251, "plugin_data": "{\"choices\": \"During hospital stay\\r\\nOn readmission\\r\\nPost discharge\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"When was surgical site infection detected\", \"name\": \"when_was_surgical_site_infection_detected\", \"required\": false}"}, {"plugin_uid": "select", "position": 252, "plugin_data": "{\"choices\": \"Home\\r\\nRelative\\r\\nNursing home\\r\\nOther\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Discharged to\", \"name\": \"discharged_to\", \"required\": false}"}, {"plugin_uid": "content_text", "position": 253, "plugin_data": "{\"text\": \"Blood cultures\"}"}, {"plugin_uid": "date", "position": 254, "plugin_data": "{\"initial\": null, \"input_formats\": \"\", \"label\": \"Date sent\", \"name\": \"date_sent\", \"help_text\": \"\", \"required\": false}"}, {"plugin_uid": "radio", "position": 255, "plugin_data": "{\"choices\": \"Yes\\r\\nNo\", \"initial\": \"\", \"help_text\": \"\", \"label\": \"Contaminated specimen\", \"name\": \"contaminated_specimen\", \"required\": false}"}, {"plugin_uid": "text", "position": 256, "plugin_data": "{\"initial\": \"\", \"help_text\": \"\", \"label\": \"Growth\", \"required\": false, \"name\": \"growth\", \"placeholder\": \"\", \"max_length\": 255}"}, {"plugin_uid": "text", "position": 257, "plugin_data": "{\"initial\": \"\", \"help_text\": \"\", \"label\": \"Sensitivity\", \"required\": false, \"name\": \"sensitivity\", \"placeholder\": \"\", \"max_length\": 255}"}], "success_page_title": "Form submitted successfully", "slug": "ssi-knee-hip", "form_handlers": [], "success_page_message": "", "is_public": false}, {"action": "", "name": "Was the survey useful?", "is_cloneable": false, "form_elements": [{"plugin_uid": "slider", "position": 1, "plugin_data": "{\"handle\": \"round\", \"max_value\": 100, \"label\": \"Did you find the survey useful?\", \"label_end\": \"Yes\", \"min_value\": 0, \"tooltip\": \"show\", \"show_endpoints_as\": \"labeled_ticks\", \"help_text\": \"\", \"initial\": 50, \"label_start\": \"No\", \"name\": \"did_you_find_the_survey_useful\", \"step\": 1, \"required\": true}"}], "success_page_title": "", "slug": "slider-form", "form_handlers": [{"plugin_uid": "db_store", "plugin_data": null}], "success_page_message": "", "is_public": false}], "success_page_title": "", "slug": "test-form-wizard", "form_wizard_handlers": [{"plugin_uid": "db_store", "plugin_data": null}], "success_page_message": "", "is_public": false} \ No newline at end of file diff --git a/examples/saved_forms_in_json_format/test-private-form.json b/examples/saved_forms_in_json_format/test-private-form.json new file mode 100755 index 00000000..b7990bbc --- /dev/null +++ b/examples/saved_forms_in_json_format/test-private-form.json @@ -0,0 +1 @@ +{"form_handlers": [{"plugin_data": null, "plugin_uid": "db_store"}], "name": "Test private form", "action": "", "success_page_message": "", "slug": "test-private-form", "success_page_title": "", "form_elements": [{"plugin_data": "{\"required\": true, \"placeholder\": \"\", \"help_text\": \"\", \"max_length\": 255, \"initial\": \"\", \"label\": \"E-mail\", \"name\": \"e_mail\"}", "plugin_uid": "email", "position": 165}, {"plugin_data": "{\"required\": true, \"placeholder\": \"\", \"help_text\": \"\", \"max_length\": 255, \"initial\": \"\", \"label\": \"Full name\", \"name\": \"full_name\"}", "plugin_uid": "text", "position": 166}, {"plugin_data": "{\"required\": true, \"placeholder\": \"\", \"help_text\": \"\", \"initial\": \"\", \"label\": \"Question\", \"name\": \"question\"}", "plugin_uid": "textarea", "position": 167}, {"plugin_data": "{\"readonly_value\": false, \"name\": \"nombre\", \"help_text\": \"\", \"required\": true, \"min_value\": \"\", \"multiple_value\": false, \"initial\": \"\", \"type_value\": \"text\", \"list_value\": \"5\", \"disabled_value\": false, \"step_value\": null, \"autofocus_value\": true, \"placeholder\": \"nombre\", \"pattern_value\": \"\", \"autocomplete_value\": true, \"label\": \"nombre\", \"max_length\": 255, \"max_value\": \"6\"}", "plugin_uid": "input", "position": 168}, {"plugin_data": "{\"name\": \"apellido\", \"required\": true, \"help_text\": \"\", \"placeholder\": \"apellido\", \"initial\": \"\", \"max_length\": 255, \"label\": \"apellido\"}", "plugin_uid": "text", "position": 169}], "is_public": false, "is_cloneable": false, "position": null} \ No newline at end of file diff --git a/examples/saved_forms_in_json_format/test-sliders.json b/examples/saved_forms_in_json_format/test-sliders.json new file mode 100755 index 00000000..8d0379ad --- /dev/null +++ b/examples/saved_forms_in_json_format/test-sliders.json @@ -0,0 +1 @@ +{"name": "Test sliders", "is_cloneable": false, "form_wizard_forms": [{"action": "", "name": "Test slider form", "is_cloneable": false, "form_elements": [{"plugin_uid": "slider", "position": 1, "plugin_data": "{\"step\": 10, \"initial\": 50, \"tooltip\": \"show\", \"label\": \"Slider variant 1\", \"name\": \"slider_variant_1\", \"max_value\": 100, \"help_text\": \"\", \"custom_ticks\": \"0, Start\\r\\n50, Middle\\r\\n100, End\", \"min_value\": 0, \"show_endpoints_as\": \"labeled_ticks\", \"label_end\": \"\", \"label_start\": \"\", \"required\": false, \"handle\": \"square\"}"}, {"plugin_uid": "slider", "position": 2, "plugin_data": "{\"step\": 20, \"initial\": 40, \"tooltip\": \"show\", \"label\": \"Slider variant 2\", \"name\": \"slider_variant_2\", \"max_value\": 100, \"help_text\": \"\", \"custom_ticks\": \"0\\r\\n20\\r\\n40\\r\\n60\\r\\n80\\r\\n100\", \"min_value\": 0, \"show_endpoints_as\": \"labeled_ticks\", \"label_end\": \"\", \"label_start\": \"\", \"required\": false, \"handle\": \"round\"}"}, {"plugin_uid": "slider", "position": 3, "plugin_data": "{\"step\": 25, \"initial\": 50, \"tooltip\": \"show\", \"label\": \"Slider variant 3\", \"name\": \"slider_variant_3\", \"max_value\": 100, \"help_text\": \"\", \"custom_ticks\": \"\", \"min_value\": 0, \"show_endpoints_as\": \"labels\", \"label_end\": \"100%\", \"label_start\": \"0%\", \"required\": false, \"handle\": \"triangle\"}"}, {"plugin_uid": "slider", "position": 4, "plugin_data": "{\"step\": 10, \"initial\": 50, \"tooltip\": \"hide\", \"label\": \"Slider variant 4\", \"name\": \"slider_variant_4\", \"max_value\": 100, \"help_text\": \"\", \"custom_ticks\": \"\", \"min_value\": 0, \"show_endpoints_as\": \"labels\", \"label_end\": \"\", \"label_start\": \"\", \"required\": false, \"handle\": \"round\"}"}], "success_page_title": "", "slug": "test-slider-form", "form_handlers": [], "success_page_message": "", "is_public": false}, {"action": "", "name": "Flight form", "is_cloneable": false, "form_elements": [{"plugin_uid": "radio", "position": 1, "plugin_data": "{\"help_text\": \"\", \"required\": true, \"initial\": \"\", \"label\": \"Arrival/Departure\", \"name\": \"arrival_departure\", \"choices\": \"A, Arrival\\r\\nD, Departure\\r\\nO, Overfly\"}"}, {"plugin_uid": "text", "position": 2, "plugin_data": "{\"help_text\": \"\", \"max_length\": 50, \"initial\": \"\", \"label\": \"Callsign\", \"name\": \"callsign\", \"placeholder\": \"\", \"required\": true}"}, {"plugin_uid": "text", "position": 3, "plugin_data": "{\"help_text\": \"\", \"max_length\": 255, \"initial\": \"\", \"label\": \"Airport\", \"name\": \"airport\", \"placeholder\": \"Origin/Destination\", \"required\": true}"}, {"plugin_uid": "datetime", "position": 4, "plugin_data": "{\"help_text\": \"\", \"required\": true, \"initial\": null, \"label\": \"Schedule\", \"name\": \"time\", \"input_formats\": \"\"}"}], "success_page_title": "OK", "slug": "flight-form", "form_handlers": [{"plugin_uid": "db_store", "plugin_data": null}], "success_page_message": "Flight updated", "is_public": false}], "success_page_title": "", "slug": "test-sliders", "form_wizard_handlers": [{"plugin_uid": "db_store", "plugin_data": null}], "success_page_message": "", "is_public": false} \ No newline at end of file diff --git a/examples/saved_forms_in_json_format/testing-interesting-project.json b/examples/saved_forms_in_json_format/testing-interesting-project.json new file mode 100755 index 00000000..249572b3 --- /dev/null +++ b/examples/saved_forms_in_json_format/testing-interesting-project.json @@ -0,0 +1 @@ +{"action": "", "name": "Testing interesting project", "is_cloneable": false, "form_elements": [{"plugin_uid": "content_text", "position": 1, "plugin_data": "{\"text\": \"Lorem Ipsum - \\u044d\\u0442\\u043e \\u0442\\u0435\\u043a\\u0441\\u0442-\\\"\\u0440\\u044b\\u0431\\u0430\\\", \\u0447\\u0430\\u0441\\u0442\\u043e \\u0438\\u0441\\u043f\\u043e\\u043b\\u044c\\u0437\\u0443\\u0435\\u043c\\u044b\\u0439 \\u0432 \\u043f\\u0435\\u0447\\u0430\\u0442\\u0438 \\u0438 \\u0432\\u044d\\u0431-\\u0434\\u0438\\u0437\\u0430\\u0439\\u043d\\u0435. Lorem Ipsum \\u044f\\u0432\\u043b\\u044f\\u0435\\u0442\\u0441\\u044f \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e\\u0439 \\\"\\u0440\\u044b\\u0431\\u043e\\u0439\\\" \\u0434\\u043b\\u044f \\u0442\\u0435\\u043a\\u0441\\u0442\\u043e\\u0432 \\u043d\\u0430 \\u043b\\u0430\\u0442\\u0438\\u043d\\u0438\\u0446\\u0435 \\u0441 \\u043d\\u0430\\u0447\\u0430\\u043b\\u0430 XVI \\u0432\\u0435\\u043a\\u0430. \\u0412 \\u0442\\u043e \\u0432\\u0440\\u0435\\u043c\\u044f \\u043d\\u0435\\u043a\\u0438\\u0439 \\u0431\\u0435\\u0437\\u044b\\u043c\\u044f\\u043d\\u043d\\u044b\\u0439 \\u043f\\u0435\\u0447\\u0430\\u0442\\u043d\\u0438\\u043a \\u0441\\u043e\\u0437\\u0434\\u0430\\u043b \\u0431\\u043e\\u043b\\u044c\\u0448\\u0443\\u044e \\u043a\\u043e\\u043b\\u043b\\u0435\\u043a\\u0446\\u0438\\u044e \\u0440\\u0430\\u0437\\u043c\\u0435\\u0440\\u043e\\u0432 \\u0438 \\u0444\\u043e\\u0440\\u043c \\u0448\\u0440\\u0438\\u0444\\u0442\\u043e\\u0432, \\u0438\\u0441\\u043f\\u043e\\u043b\\u044c\\u0437\\u0443\\u044f Lorem Ipsum \\u0434\\u043b\\u044f \\u0440\\u0430\\u0441\\u043f\\u0435\\u0447\\u0430\\u0442\\u043a\\u0438 \\u043e\\u0431\\u0440\\u0430\\u0437\\u0446\\u043e\\u0432. Lorem Ipsum \\u043d\\u0435 \\u0442\\u043e\\u043b\\u044c\\u043a\\u043e \\u0443\\u0441\\u043f\\u0435\\u0448\\u043d\\u043e \\u043f\\u0435\\u0440\\u0435\\u0436\\u0438\\u043b \\u0431\\u0435\\u0437 \\u0437\\u0430\\u043c\\u0435\\u0442\\u043d\\u044b\\u0445 \\u0438\\u0437\\u043c\\u0435\\u043d\\u0435\\u043d\\u0438\\u0439 \\u043f\\u044f\\u0442\\u044c \\u0432\\u0435\\u043a\\u043e\\u0432, \\u043d\\u043e \\u0438 \\u043f\\u0435\\u0440\\u0435\\u0448\\u0430\\u0433\\u043d\\u0443\\u043b \\u0432 \\u044d\\u043b\\u0435\\u043a\\u0442\\u0440\\u043e\\u043d\\u043d\\u044b\\u0439 \\u0434\\u0438\\u0437\\u0430\\u0439\\u043d. \\u0415\\u0433\\u043e \\u043f\\u043e\\u043f\\u0443\\u043b\\u044f\\u0440\\u0438\\u0437\\u0430\\u0446\\u0438\\u0438 \\u0432 \\u043d\\u043e\\u0432\\u043e\\u0435 \\u0432\\u0440\\u0435\\u043c\\u044f \\u043f\\u043e\\u0441\\u043b\\u0443\\u0436\\u0438\\u043b\\u0438 \\u043f\\u0443\\u0431\\u043b\\u0438\\u043a\\u0430\\u0446\\u0438\\u044f \\u043b\\u0438\\u0441\\u0442\\u043e\\u0432 Letraset \\u0441 \\u043e\\u0431\\u0440\\u0430\\u0437\\u0446\\u0430\\u043c\\u0438 Lorem Ipsum \\u0432 60-\\u0445 \\u0433\\u043e\\u0434\\u0430\\u0445 \\u0438, \\u0432 \\u0431\\u043e\\u043b\\u0435\\u0435 \\u043d\\u0435\\u0434\\u0430\\u0432\\u043d\\u0435\\u0435 \\u0432\\u0440\\u0435\\u043c\\u044f, \\u043f\\u0440\\u043e\\u0433\\u0440\\u0430\\u043c\\u043c\\u044b \\u044d\\u043b\\u0435\\u043a\\u0442\\u0440\\u043e\\u043d\\u043d\\u043e\\u0439 \\u0432\\u0451\\u0440\\u0441\\u0442\\u043a\\u0438 \\u0442\\u0438\\u043f\\u0430 Aldus PageMaker, \\u0432 \\u0448\\u0430\\u0431\\u043b\\u043e\\u043d\\u0430\\u0445 \\u043a\\u043e\\u0442\\u043e\\u0440\\u044b\\u0445 \\u0438\\u0441\\u043f\\u043e\\u043b\\u044c\\u0437\\u0443\\u0435\\u0442\\u0441\\u044f Lorem Ipsum.\"}"}, {"plugin_uid": "input", "position": 2, "plugin_data": "{\"autocomplete_value\": true, \"min_value\": \"\", \"max_length\": 255, \"multiple_value\": false, \"name\": \"ttohemy_oh_ncnojib3yetcr\", \"readonly_value\": false, \"label\": \"\\u041f\\u043e\\u0447\\u0435\\u043c\\u0443 \\u043e\\u043d \\u0438\\u0441\\u043f\\u043e\\u043b\\u044c\\u0437\\u0443\\u0435\\u0442\\u0441\\u044f?\", \"list_value\": \"\", \"help_text\": \"\\u0414\\u0430\\u0432\\u043d\\u043e \\u0432\\u044b\\u044f\\u0441\\u043d\\u0435\\u043d\\u043e, \\u0447\\u0442\\u043e \\u043f\\u0440\\u0438 \\u043e\\u0446\\u0435\\u043d\\u043a\\u0435 \\u0434\\u0438\\u0437\\u0430\\u0439\\u043d\\u0430 \\u0438 \\u043a\\u043e\\u043c\\u043f\\u043e\\u0437\\u0438\\u0446\\u0438\\u0438 \\u0447\\u0438\\u0442\\u0430\\u0435\\u043c\\u044b\\u0439 \\u0442\\u0435\\u043a\\u0441\\u0442 \\u043c\\u0435\\u0448\\u0430\\u0435\\u0442 \\u0441\\u043e\\u0441\\u0440\\u0435\\u0434\\u043e\\u0442\\u043e\\u0447\\u0438\\u0442\\u044c\\u0441\\u044f. Lorem Ipsum \\u0438\\u0441\\u043f\\u043e\\u043b\\u044c\\u0437\\u0443\\u044e\\u0442 \\u043f\\u043e\\u0442\\u043e\\u043c\\u0443, \\u0447\\u0442\\u043e \\u0442\\u043e\\u0442 \\u043e\\u0431\\u0435\\u0441\\u043f\\u0435\\u0447\\u0438\\u0432\\u0430\\u0435\\u0442 \\u0431\\u043e\\u043b\\u0435\\u0435 \\u0438\\u043b\\u0438 \\u043c\\u0435\\u043d\\u0435\\u0435 \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e\\u0435 \\u0437\\u0430\\u043f\\u043e\\u043b\\u043d\\u0435\\u043d\\u0438\\u0435 \\u0448\\u0430\\u0431\\u043b\\u043e\\u043d\\u0430, \\u0430 \\u0442\\u0430\\u043a\\u0436\\u0435 \\u0440\\u0435\\u0430\\u043b\\u044c\\u043d\\u043e\\u0435 \\u0440\\u0430\\u0441\\u043f\\u0440\\u0435\\u0434\\u0435\\u043b\\u0435\\u043d\\u0438\\u0435 \\u0431\\u0443\\u043a\\u0432 \\u0438 \\u043f\\u0440\\u043e\\u0431\\u0435\\u043b\\u043e\\u0432 \\u0432 \\u0430\\u0431\\u0437\\u0430\\u0446\\u0430\\u0445, \\u043a\\u043e\\u0442\\u043e\\u0440\\u043e\\u0435 \\u043d\\u0435 \\u043f\\u043e\\u043b\\u0443\\u0447\\u0430\\u0435\\u0442\\u0441\\u044f \\u043f\\u0440\\u0438 \\u043f\\u0440\\u043e\\u0441\\u0442\\u043e\\u0439 \\u0434\\u0443\\u0431\\u043b\\u0438\\u043a\\u0430\\u0446\\u0438\\u0438 \\\"\\u0417\\u0434\\u0435\\u0441\\u044c \\u0432\\u0430\\u0448 \\u0442\\u0435\\u043a\\u0441\\u0442.. \\u0417\\u0434\\u0435\\u0441\\u044c \\u0432\\u0430\\u0448 \\u0442\\u0435\\u043a\\u0441\\u0442.. \\u0417\\u0434\\u0435\\u0441\\u044c \\u0432\\u0430\\u0448 \\u0442\\u0435\\u043a\\u0441\\u0442..\\\" \\u041c\\u043d\\u043e\\u0433\\u0438\\u0435 \\u043f\\u0440\\u043e\\u0433\\u0440\\u0430\\u043c\\u043c\\u044b \\u044d\\u043b\\u0435\\u043a\\u0442\\u0440\\u043e\\u043d\\u043d\\u043e\\u0439 \\u0432\\u0451\\u0440\\u0441\\u0442\\u043a\\u0438 \\u0438 \\u0440\\u0435\\u0434\\u0430\\u043a\\u0442\\u043e\\u0440\\u044b HTML \\u0438\\u0441\\u043f\\u043e\\u043b\\u044c\\u0437\\u0443\\u044e\\u0442 Lorem Ipsum \\u0432 \\u043a\\u0430\\u0447\\u0435\\u0441\\u0442\\u0432\\u0435 \\u0442\\u0435\\u043a\\u0441\\u0442\\u0430 \\u043f\\u043e \\u0443\\u043c\\u043e\\u043b\\u0447\\u0430\\u043d\\u0438\\u044e, \\u0442\\u0430\\u043a \\u0447\\u0442\\u043e \\u043f\\u043e\\u0438\\u0441\\u043a \\u043f\\u043e \\u043a\\u043b\\u044e\\u0447\\u0435\\u0432\\u044b\\u043c \\u0441\\u043b\\u043e\\u0432\\u0430\\u043c \\\"lorem ipsum\\\" \\u0441\\u0440\\u0430\\u0437\\u0443 \\u043f\\u043e\\u043a\\u0430\\u0437\\u044b\\u0432\\u0430\\u0435\\u0442, \\u043a\\u0430\\u043a \\u043c\\u043d\\u043e\\u0433\\u043e \\u0432\\u0435\\u0431-\\u0441\\u0442\\u0440\\u0430\\u043d\\u0438\\u0446 \\u0432\\u0441\\u0451 \\u0435\\u0449\\u0451 \\u0434\\u043e\\u0436\\u0438\\u0434\\u0430\\u044e\\u0442\\u0441\\u044f \\u0441\\u0432\\u043e\\u0435\\u0433\\u043e \\u043d\\u0430\\u0441\\u0442\\u043e\\u044f\\u0449\\u0435\\u0433\\u043e \\u0440\\u043e\\u0436\\u0434\\u0435\\u043d\\u0438\\u044f. \\u0417\\u0430 \\u043f\\u0440\\u043e\\u0448\\u0435\\u0434\\u0448\\u0438\\u0435 \\u0433\\u043e\\u0434\\u044b \\u0442\\u0435\\u043a\\u0441\\u0442 Lorem Ipsum \\u043f\\u043e\\u043b\\u0443\\u0447\\u0438\\u043b \\u043c\\u043d\\u043e\\u0433\\u043e \\u0432\\u0435\\u0440\\u0441\\u0438\\u0439. \\u041d\\u0435\\u043a\\u043e\\u0442\\u043e\\u0440\\u044b\\u0435 \\u0432\\u0435\\u0440\\u0441\\u0438\\u0438 \\u043f\\u043e\\u044f\\u0432\\u0438\\u043b\\u0438\\u0441\\u044c \\u043f\\u043e \\u043e\\u0448\\u0438\\u0431\\u043a\\u0435, \\u043d\\u0435\\u043a\\u043e\\u0442\\u043e\\u0440\\u044b\\u0435 - \\u043d\\u0430\\u043c\\u0435\\u0440\\u0435\\u043d\\u043d\\u043e (\\u043d\\u0430\\u043f\\u0440\\u0438\\u043c\\u0435\\u0440, \\u044e\\u043c\\u043e\\u0440\\u0438\\u0441\\u0442\\u0438\\u0447\\u0435\\u0441\\u043a\\u0438\\u0435 \\u0432\\u0430\\u0440\\u0438\\u0430\\u043d\\u0442\\u044b).\", \"required\": true, \"placeholder\": \"\", \"step_value\": null, \"disabled_value\": false, \"max_value\": \"\", \"initial\": \"\", \"type_value\": \"text\", \"autofocus_value\": false, \"pattern_value\": \"\"}"}, {"plugin_uid": "ip_address", "position": 3, "plugin_data": "{\"placeholder\": \"\", \"unpack_ipv4\": false, \"required\": false, \"name\": \"ip\", \"label\": \"IP\", \"help_text\": \"\", \"max_length\": 255, \"initial\": \"\", \"protocol\": \"both\"}"}, {"plugin_uid": "slider", "position": 4, "plugin_data": "{\"step\": 1, \"required\": false, \"name\": \"dabho_bbircheho\", \"label\": \"\\u0414\\u0430\\u0432\\u043d\\u043e \\u0432\\u044b\\u044f\\u0441\\u043d\\u0435\\u043d\\u043e\", \"label_start\": \"\", \"label_end\": \"\", \"min_value\": 0, \"tooltip\": \"show\", \"help_text\": \"\", \"max_value\": 100, \"show_endpoints_as\": \"labels\", \"initial\": 50, \"handle\": \"round\", \"custom_ticks\": \"\"}"}, {"plugin_uid": "datetime", "position": 5, "plugin_data": "{\"input_formats\": \"\", \"required\": false, \"name\": \"data_npobepkn\", \"label\": \"\\u0414\\u0430\\u0442\\u0430 \\u043f\\u0440\\u043e\\u0432\\u0435\\u0440\\u043a\\u0438\", \"help_text\": \"\", \"initial\": null}"}, {"plugin_uid": "file", "position": 6, "plugin_data": "{\"max_length\": 255, \"required\": true, \"name\": \"oanji\", \"label\": \"\\u0424\\u0430\\u0439\\u043b\", \"help_text\": \"\", \"initial\": \"\"}"}], "success_page_title": "Test Form", "slug": "testing-interesting-project", "form_handlers": [{"plugin_uid": "db_store", "plugin_data": null}], "success_page_message": "Test Form description", "is_public": false} \ No newline at end of file From d0d3b75b4bffc5835264e67850c8477719d394f0 Mon Sep 17 00:00:00 2001 From: Artur Barseghyan Date: Tue, 9 May 2017 20:43:51 +0200 Subject: [PATCH 3/7] add readme for saved forms --- examples/saved_forms_in_json_format/README.rst | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 examples/saved_forms_in_json_format/README.rst diff --git a/examples/saved_forms_in_json_format/README.rst b/examples/saved_forms_in_json_format/README.rst new file mode 100644 index 00000000..ca0f9f3e --- /dev/null +++ b/examples/saved_forms_in_json_format/README.rst @@ -0,0 +1,4 @@ +Saved forms in JSON format +========================== +A nice collection of saved ``django-fobi`` forms. Importable using the +import functionality. From 46ba85623715a196ca6dff9bb35a4a7a378ab6ce Mon Sep 17 00:00:00 2001 From: Artur Barseghyan Date: Wed, 10 May 2017 00:28:14 +0200 Subject: [PATCH 4/7] prepare 0.11.3 --- CHANGELOG.rst | 7 + examples/simple/foo/fobi_form_callbacks.py | 63 ++++++++- setup.py | 2 +- src/fobi/__init__.py | 4 +- src/fobi/base.py | 131 ++++++++++++++---- .../contrib/apps/drf_integration/README.rst | 45 ++++++ .../contrib/apps/drf_integration/TODOS.rst | 14 +- src/fobi/contrib/apps/drf_integration/base.py | 50 +++---- .../contrib/apps/drf_integration/views.py | 37 ++--- 9 files changed, 272 insertions(+), 81 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c1a98244..dac8ffbd 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -15,6 +15,13 @@ are used for versioning (schema follows below): 0.3.4 to 0.4). - All backwards incompatible changes are mentioned in this document. +0.11.3 +------ +2017-05-10 + +- Concept of integration callbacks introduced and implemented for the + ``drf_integration`` sub-package. + 0.11.2 ------ 2017-05-09 diff --git a/examples/simple/foo/fobi_form_callbacks.py b/examples/simple/foo/fobi_form_callbacks.py index 3f3eb10a..abc375da 100644 --- a/examples/simple/foo/fobi_form_callbacks.py +++ b/examples/simple/foo/fobi_form_callbacks.py @@ -2,15 +2,23 @@ from __future__ import print_function import logging -from fobi.base import FormCallback, form_callback_registry +from fobi.base import ( + form_callback_registry, + FormCallback, + integration_form_callback_registry, + IntegrationFormCallback, +) + from fobi.constants import ( CALLBACK_BEFORE_FORM_VALIDATION, - CALLBACK_FORM_VALID_BEFORE_SUBMIT_PLUGIN_FORM_DATA, + CALLBACK_FORM_INVALID, CALLBACK_FORM_VALID, CALLBACK_FORM_VALID_AFTER_FORM_HANDLERS, - CALLBACK_FORM_INVALID + CALLBACK_FORM_VALID_BEFORE_SUBMIT_PLUGIN_FORM_DATA, ) +from fobi.contrib.apps.drf_integration import UID as INTEGRATE_WITH + logger = logging.getLogger('fobi') __all__ = ( @@ -18,6 +26,12 @@ __all__ = ( 'DummyInvalidCallback', ) +# ************************************************************* +# ************************************************************* +# ********************** Core callbacks *********************** +# ************************************************************* +# ************************************************************* + # ************************************************************* # **************** Save as foo callback *********************** # ************************************************************* @@ -51,3 +65,46 @@ class DummyInvalidCallback(FormCallback): form_callback_registry.register(DummyInvalidCallback) + +# ************************************************************* +# ************************************************************* +# ****************** DRF integration callbacks **************** +# ************************************************************* +# ************************************************************* + + +# ************************************************************* +# **************** Save as foo callback *********************** +# ************************************************************* + + +class DRFSaveAsFooItem(IntegrationFormCallback): + """Save the form as a foo item, if certain conditions are met.""" + + stage = CALLBACK_FORM_VALID + integrate_with = INTEGRATE_WITH + + def callback(self, form_entry, request, **kwargs): + """Custom callback login comes here.""" + logger.debug("Great! Your form is valid!") + + +integration_form_callback_registry.register(DRFSaveAsFooItem) + +# ************************************************************* +# **************** Save as foo callback *********************** +# ************************************************************* + + +class DRFDummyInvalidCallback(IntegrationFormCallback): + """Saves the form as a foo item, if certain conditions are met.""" + + stage = CALLBACK_FORM_INVALID + integrate_with = INTEGRATE_WITH + + def callback(self, form_entry, request, **kwargs): + """Custom callback login comes here.""" + logger.debug("Damn! You've made a mistake, boy!") + + +integration_form_callback_registry.register(DRFDummyInvalidCallback) diff --git a/setup.py b/setup.py index 4a848b78..018ccf82 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ import sys from distutils.version import LooseVersion from setuptools import setup, find_packages -version = '0.11.2' +version = '0.11.3' # *************************************************************************** # ************************** Python version ********************************* diff --git a/src/fobi/__init__.py b/src/fobi/__init__.py index 31211c82..3c5056a7 100644 --- a/src/fobi/__init__.py +++ b/src/fobi/__init__.py @@ -1,6 +1,6 @@ __title__ = 'django-fobi' -__version__ = '0.11.2' -__build__ = 0x00007d +__version__ = '0.11.3' +__build__ = 0x00007e __author__ = 'Artur Barseghyan ' __copyright__ = '2014-2017 Artur Barseghyan' __license__ = 'GPL 2.0/LGPL 2.1' diff --git a/src/fobi/base.py b/src/fobi/base.py index 816dc3bb..8b3e443a 100644 --- a/src/fobi/base.py +++ b/src/fobi/base.py @@ -146,6 +146,9 @@ __all__ = ( 'IntegrationFormHandlerPlugin', 'IntegrationFormHandlerPluginDataStorage', 'IntegrationFormHandlerPluginRegistry', + 'IntegrationFormCallbackRegistry', + 'IntegrationFormCallback', + 'integration_form_callback_registry', 'run_form_handlers', 'run_form_wizard_handlers', 'theme_registry', @@ -2060,7 +2063,7 @@ class IntegrationFormHandlerPlugin(BasePlugin): is_hidden = False -class FormCallback(object): +class BaseFormCallback(object): """Base form callback.""" stage = None @@ -2069,6 +2072,10 @@ class FormCallback(object): """Constructor.""" assert self.stage in CALLBACK_STAGES + +class FormCallback(BaseFormCallback): + """Form callback.""" + def _callback(self, form_entry, request, form): """Callback (internal method). @@ -2098,31 +2105,45 @@ class FormCallback(object): "subclass.".format(self.__class__.__name__) ) - # def custom_field_instances_callback(self, integrate_with, form_entry, - # request, **kwargs): - # """Custom field instances callback. - # - # :param str integrate_with: - # :param fobi.models.FormEntry form_entry: Instance of - # ``fobi.models.FormEntry``. - # :param django.http.HttpRequest request: - # :param kwargs: - # """ - # try: - # custom_callback = self.get_custom_field_instance_callback( - # integrate_with=integrate_with - # ) - # return custom_callback.callback( - # form_entry=form_entry, - # request=request, - # **kwargs - # ) - # except Exception as err: - # logger.debug( - # "Error in class %s. Details: %s", - # self.__class__.__name__, - # str(err) - # ) + +class IntegrationFormCallback(object): + """Integration form callback.""" + + integrate_with = None + + def __init__(self): + """Constructor.""" + assert self.stage in CALLBACK_STAGES + assert self.integrate_with is not None + + def _callback(self, form_entry, request, **kwargs): + """Callback (internal method). + + Calling the ``callback`` method in a safe way. + """ + try: + return self.callback(form_entry, request, **kwargs) + except Exception as err: + logger.debug( + "Error in class %s. Details: %s", + self.__class__.__name__, + str(err) + ) + + def callback(self, form_entry, request, **kwargs): + """Callback. + + Custom callback code should be implemented here. + + :param fobi.models.FormEntry form_entry: Instance of + ``fobi.models.FormEntry``. + :param django.http.HttpRequest request: + :param django.forms.Form form: + """ + raise NotImplementedError( + "You should implement ``callback`` method in your {0} " + "subclass.".format(self.__class__.__name__) + ) class ClassProperty(property): @@ -2507,6 +2528,61 @@ class FormCallbackRegistry(object): return callbacks +class IntegrationFormCallbackRegistry(object): + """Registry of callbacks for integration plugins. + + Holds callbacks for stages listed in the + ``fobi.constants.CALLBACK_STAGES``. + """ + + def __init__(self): + """Constructor.""" + self._registry = defaultdict(lambda: defaultdict(list)) + + @property + def registry(self): + return self._registry + + def uidfy(self, cls): + """Makes a UID string from the class given. + + :param mixed cls: + :return string: + """ + return "{0}.{1}".format(cls.__module__, cls.__name__) + + def register(self, cls): + """Registers the plugin in the registry. + + :param mixed cls: + """ + if not issubclass(cls, IntegrationFormCallback): + raise InvalidRegistryItemType( + "Invalid item type `{0}` for registry " + "`{1}`".format(cls, self.__class__) + ) + if cls in self._registry[cls.integrate_with][cls.stage]: + return False + else: + self._registry[cls.integrate_with][cls.stage].append(cls) + return True + + def get_callbacks(self, integrate_with, stage=None): + """Get callbacks for the stage given. + + :param str integrate_with: + :param string stage: + :return list: + """ + if stage: + return self._registry[integrate_with].get(stage, []) + else: + callbacks = [] + for stage_callbacks in self._registry[integrate_with].values(): + callbacks += stage_callbacks + return callbacks + + class BasePluginWidgetRegistry(object): """Registry of plugins widgets (renderers).""" type = None @@ -2630,6 +2706,9 @@ theme_registry = ThemeRegistry() # Register action plugins by calling form_action_plugin_registry.register() form_callback_registry = FormCallbackRegistry() +# Register action plugins by calling form_action_plugin_registry.register() +integration_form_callback_registry = IntegrationFormCallbackRegistry() + # Register plugin widgets by calling # form_element_plugin_widget_registry.register() form_element_plugin_widget_registry = FormElementPluginWidgetRegistry() diff --git a/src/fobi/contrib/apps/drf_integration/README.rst b/src/fobi/contrib/apps/drf_integration/README.rst index 31196c0f..21937bec 100644 --- a/src/fobi/contrib/apps/drf_integration/README.rst +++ b/src/fobi/contrib/apps/drf_integration/README.rst @@ -247,6 +247,51 @@ PUT {DATA} +Callbacks +--------- +Callbacks work just the same way the core callbacks work. + +fobi_form_callbacks.py +~~~~~~~~~~~~~~~~~~~~~~ +.. code-block:: python + + from fobi.base import ( + integration_form_callback_registry, + IntegrationFormCallback, + ) + + from fobi.constants import ( + CALLBACK_BEFORE_FORM_VALIDATION, + CALLBACK_FORM_INVALID, + CALLBACK_FORM_VALID, + CALLBACK_FORM_VALID_AFTER_FORM_HANDLERS, + CALLBACK_FORM_VALID_BEFORE_SUBMIT_PLUGIN_FORM_DATA, + ) + + from fobi.contrib.apps.drf_integration import UID as INTEGRATE_WITH + + + class DRFSaveAsFooItem(IntegrationFormCallback): + """Save the form as a foo item, if certain conditions are met.""" + + stage = CALLBACK_FORM_VALID + integrate_with = INTEGRATE_WITH + + def callback(self, form_entry, request, **kwargs): + """Custom callback login comes here.""" + logger.debug("Great! Your form is valid!") + + + class DRFDummyInvalidCallback(IntegrationFormCallback): + """Saves the form as a foo item, if certain conditions are met.""" + + stage = CALLBACK_FORM_INVALID + integrate_with = INTEGRATE_WITH + + def callback(self, form_entry, request, **kwargs): + """Custom callback login comes here.""" + logger.debug("Damn! You've made a mistake, boy!") + Testing ------- To test Django REST framework integration package only, run the following diff --git a/src/fobi/contrib/apps/drf_integration/TODOS.rst b/src/fobi/contrib/apps/drf_integration/TODOS.rst index c8d757b4..2259950c 100644 --- a/src/fobi/contrib/apps/drf_integration/TODOS.rst +++ b/src/fobi/contrib/apps/drf_integration/TODOS.rst @@ -9,8 +9,8 @@ Must haves instances. Do it this way and not the other way, since things get complicated when we start to deal with wizards. + Find out how to handle further the submitted data? It should be in - accordance with fobi concepts of loosely couple parts. After successful - submission, the fobi form callbacks, handlers and that kind of things + accordance with ``fobi`` concepts of loosely couple parts. After successful + submission, the ``fobi`` form callbacks, handlers and that kind of things should be fired for the given form entry. Thus, it should likely be the same in this case. Probably each CustomFieldInstancePlugin should get a method ``drf_submit_plugin_form_data``, which should mimic the @@ -33,13 +33,11 @@ Should haves ------------ + Find why HiddenInput tests fail (in terms of Django REST framework it's a read-only field). -- Add custom field instance callback for handling data of the custom field - instances. Do it this way and not the other way, since things get - complicated when we start to deal with wizards. +- Add Integration form callbacks for handling data of the integration plugins. - Add more fields (relation- and presentational- fields). - Think of what to do with presentational fields (perhaps just display?) -- Somehow, the `file` plugin data, when submitted, isn't shown properly in the - posted data (by DRF), although is posted 100% correctly. +- Somehow, the ``file`` plugin data, when submitted, isn't shown properly in + the posted data (by DRF), although is posted 100% correctly. - In the API form view, use memoize technique or cache the value somehow to reduce the number of queries. @@ -49,4 +47,4 @@ Could haves Would haves ----------- -- Remove codebin.py at the end. \ No newline at end of file +- Remove codebin.py at the end. diff --git a/src/fobi/contrib/apps/drf_integration/base.py b/src/fobi/contrib/apps/drf_integration/base.py index b72c0acf..7324fad8 100644 --- a/src/fobi/contrib/apps/drf_integration/base.py +++ b/src/fobi/contrib/apps/drf_integration/base.py @@ -2,12 +2,12 @@ import copy import logging from ....base import ( - IntegrationFormElementPluginProcessor, - # form_callback_registry, - get_ignorable_form_fields, clean_dict, + get_ignorable_form_fields, get_ordered_form_handler_plugins, + integration_form_callback_registry, integration_form_element_plugin_registry, + IntegrationFormElementPluginProcessor, ) from ....helpers import get_ignorable_form_values @@ -131,27 +131,29 @@ class DRFSubmitPluginFormDataMixin(object): """ -# def fire_form_callbacks(form_entry, request, serializer, stage=None): -# """Fire form callbacks. -# -# :param fobi.models.FormEntry form_entry: -# :param django.http.HttpRequest request: -# :param rest_framework.serializers.Serializer serializer: -# :param string stage: -# :return rest_framework.serializers.Serializer serializer: -# """ -# callbacks = form_callback_registry.get_callbacks(stage=stage) -# for CallbackClass in callbacks: -# callback = CallbackClass() -# updated_serializer = callback.custom_field_instances_callback( -# integrate_with=UID, -# form_entry=form_entry, -# request=request, -# serializer=serializer, -# ) -# if updated_serializer: -# serializer = updated_serializer -# return serializer +def fire_form_callbacks(form_entry, request, serializer, stage=None): + """Fire DRF integration form callbacks. + + :param fobi.models.FormEntry form_entry: + :param django.http.HttpRequest request: + :param rest_framework.serializers.Serializer serializer: + :param string stage: + :return rest_framework.serializers.Serializer serializer: + """ + callbacks = integration_form_callback_registry.get_callbacks( + integrate_with=UID, + stage=stage + ) + for callback_cls in callbacks: + callback = callback_cls() + updated_serializer = callback.callback( + form_entry=form_entry, + request=request, + serializer=serializer + ) + if updated_serializer: + serializer = updated_serializer + return serializer def run_form_handlers(form_entry, diff --git a/src/fobi/contrib/apps/drf_integration/views.py b/src/fobi/contrib/apps/drf_integration/views.py index cb352901..0a832502 100644 --- a/src/fobi/contrib/apps/drf_integration/views.py +++ b/src/fobi/contrib/apps/drf_integration/views.py @@ -17,7 +17,7 @@ from ....constants import ( from ....models import FormEntry from .base import ( - # fire_form_callbacks, + fire_form_callbacks, run_form_handlers, submit_plugin_form_data, ) @@ -147,13 +147,13 @@ class FobiFormEntryViewSet( # Try to fetch only once. form_element_entries = form_entry.formelemententry_set.all() - # # Fire form valid before submit plugin data - # form = fire_form_callbacks( - # form_entry=form_entry, - # request=request, - # form=form, - # stage=CALLBACK_FORM_VALID_BEFORE_SUBMIT_PLUGIN_FORM_DATA - # ) + # Fire form valid before submit plugin data + form = fire_form_callbacks( + form_entry=form_entry, + request=request, + serializer=serializer, + stage=CALLBACK_FORM_VALID_BEFORE_SUBMIT_PLUGIN_FORM_DATA + ) # Fire plugin processors serializer = submit_plugin_form_data( @@ -163,9 +163,12 @@ class FobiFormEntryViewSet( ) # # Fire form valid callbacks - # form = fire_form_callbacks(form_entry=form_entry, - # request=request, form=form, - # stage=CALLBACK_FORM_VALID) + form = fire_form_callbacks( + form_entry=form_entry, + request=request, + serializer=serializer, + stage=CALLBACK_FORM_VALID + ) # Run all handlers handler_responses, handler_errors = run_form_handlers( @@ -187,9 +190,9 @@ class FobiFormEntryViewSet( ) # Fire post handler callbacks - # fire_form_callbacks( - # form_entry=form_entry, - # request=request, - # form=form, - # stage=CALLBACK_FORM_VALID_AFTER_FORM_HANDLERS - # ) + fire_form_callbacks( + form_entry=form_entry, + request=request, + serializer=serializer, + stage=CALLBACK_FORM_VALID_AFTER_FORM_HANDLERS + ) From 7a922613ae1eb68d08f2603f0322dd23fcfa957b Mon Sep 17 00:00:00 2001 From: Artur Barseghyan Date: Fri, 12 May 2017 00:52:58 +0200 Subject: [PATCH 5/7] prepare 0.11.4 --- .gitignore | 1 - CHANGELOG.rst | 9 +++ examples/django_fobi_example_app_installer.sh | 6 +- examples/requirements/demo.txt | 14 +---- examples/simple/settings/base.py | 7 ++- setup.py | 2 +- src/fobi/__init__.py | 4 +- .../contrib/apps/drf_integration/README.rst | 14 +++-- .../contrib/apps/drf_integration/TODOS.rst | 10 +-- .../contrib/apps/drf_integration/fields.py | 60 ++++++++++++++++-- .../form_elements/content/__init__.py | 0 .../content/content_image/README.rst | 28 +++++++++ .../content/content_image/__init__.py | 11 ++++ .../content/content_image/apps.py | 19 ++++++ .../content/content_image/base.py | 59 ++++++++++++++++++ .../fobi_integration_form_elements.py | 12 ++++ .../content/content_text/README.rst | 28 +++++++++ .../content/content_text/__init__.py | 11 ++++ .../content/content_text/apps.py | 19 ++++++ .../content/content_text/base.py | 61 +++++++++++++++++++ .../fobi_integration_form_elements.py | 12 ++++ .../content/content_video/README.rst | 28 +++++++++ .../content/content_video/__init__.py | 11 ++++ .../content/content_video/apps.py | 19 ++++++ .../content/content_video/base.py | 58 ++++++++++++++++++ .../fobi_integration_form_elements.py | 12 ++++ .../form_elements/fields/decimal/README.rst | 12 ++-- .../contrib/apps/drf_integration/metadata.py | 60 ++++++++++++++++++ .../contrib/apps/drf_integration/views.py | 8 ++- .../content/content_image/base.py | 15 +++++ .../content/content_text/base.py | 22 +++++++ .../content/content_video/base.py | 26 +++++++- 32 files changed, 611 insertions(+), 47 deletions(-) create mode 100644 src/fobi/contrib/apps/drf_integration/form_elements/content/__init__.py create mode 100644 src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/README.rst create mode 100644 src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/__init__.py create mode 100644 src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/apps.py create mode 100644 src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/base.py create mode 100644 src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/fobi_integration_form_elements.py create mode 100644 src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/README.rst create mode 100644 src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/__init__.py create mode 100644 src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/apps.py create mode 100644 src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/base.py create mode 100644 src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/fobi_integration_form_elements.py create mode 100644 src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/README.rst create mode 100644 src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/__init__.py create mode 100644 src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/apps.py create mode 100644 src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/base.py create mode 100644 src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/fobi_integration_form_elements.py create mode 100644 src/fobi/contrib/apps/drf_integration/metadata.py diff --git a/.gitignore b/.gitignore index beb26fd2..6ee57ee8 100644 --- a/.gitignore +++ b/.gitignore @@ -36,7 +36,6 @@ README_PARTS.rst /src/django_fobi.egg-info /src/fobi/contrib/plugins/form_elements/fields/hidden_model_object/ -/src/fobi/contrib/apps/drf_integration/form_elements/content/ /src/fobi/contrib/plugins/form_importers/mailchimp_importer/bucket.py /src/fobi/contrib/apps/wagtail_integration_/ diff --git a/CHANGELOG.rst b/CHANGELOG.rst index dac8ffbd..76dbe9c9 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -15,6 +15,15 @@ are used for versioning (schema follows below): 0.3.4 to 0.4). - All backwards incompatible changes are mentioned in this document. +0.11.4 +------ +2017-05-12 + +- Minor fixes in integration callbacks of the ``drf_integration`` sub-package. +- Added support for ``content_image``, ``content_text`` and ``content_video`` + plugins. +- Fixes in installable demo. + 0.11.3 ------ 2017-05-10 diff --git a/examples/django_fobi_example_app_installer.sh b/examples/django_fobi_example_app_installer.sh index afe7889b..fdf7e7ab 100644 --- a/examples/django_fobi_example_app_installer.sh +++ b/examples/django_fobi_example_app_installer.sh @@ -12,9 +12,9 @@ mkdir ../static/ mkdir ../db/ mkdir ../logs/ mkdir ../tmp/ -cp local_settings.example local_settings.py -./manage.py syncdb --noinput --traceback -v 3 +cp settings/local_settings.example settings/local_settings.py +#./manage.py syncdb --noinput --traceback -v 3 ./manage.py migrate --noinput ./manage.py collectstatic --noinput --traceback -v 3 ./manage.py fobi_create_test_data --traceback -v 3 -./manage.py runserver 0.0.0.0:8001 --traceback -v 3 \ No newline at end of file +./manage.py runserver 0.0.0.0:8001 --traceback -v 3 diff --git a/examples/requirements/demo.txt b/examples/requirements/demo.txt index 74588a1d..1ef8ee3c 100644 --- a/examples/requirements/demo.txt +++ b/examples/requirements/demo.txt @@ -1,13 +1 @@ --r common.txt --r djangorestframework.txt - -Django>=1.8,<1.9 -django-admin-tools>=0.7.1 -django-autoslug==1.9.3 -django-debug-toolbar==0.11 -django-formtools==1.0 -django-nine>=0.1.10 -django-nonefield>=0.1 -django-registration-redux>=1.4 -easy-thumbnails>=2.3 -vishap>=0.1.5 +-r django_1_9.txt diff --git a/examples/simple/settings/base.py b/examples/simple/settings/base.py index 2514ecd1..09d017c7 100644 --- a/examples/simple/settings/base.py +++ b/examples/simple/settings/base.py @@ -397,7 +397,7 @@ INSTALLED_APPS = [ 'rest_framework', # Django REST framework 'fobi.contrib.apps.drf_integration', # DRF integration app - # Form elements + # Form fields 'fobi.contrib.apps.drf_integration.form_elements.fields.boolean', 'fobi.contrib.apps.drf_integration.form_elements.fields' '.checkbox_select_multiple', @@ -427,6 +427,11 @@ INSTALLED_APPS = [ 'fobi.contrib.apps.drf_integration.form_elements.fields.time', 'fobi.contrib.apps.drf_integration.form_elements.fields.url', + # Presentational elements + 'fobi.contrib.apps.drf_integration.form_elements.content.content_image', + 'fobi.contrib.apps.drf_integration.form_elements.content.content_text', + 'fobi.contrib.apps.drf_integration.form_elements.content.content_video', + # Form handlers 'fobi.contrib.apps.drf_integration.form_handlers.db_store', 'fobi.contrib.apps.drf_integration.form_handlers.mail', diff --git a/setup.py b/setup.py index 018ccf82..1a885584 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ import sys from distutils.version import LooseVersion from setuptools import setup, find_packages -version = '0.11.3' +version = '0.11.4' # *************************************************************************** # ************************** Python version ********************************* diff --git a/src/fobi/__init__.py b/src/fobi/__init__.py index 3c5056a7..a977fae9 100644 --- a/src/fobi/__init__.py +++ b/src/fobi/__init__.py @@ -1,6 +1,6 @@ __title__ = 'django-fobi' -__version__ = '0.11.3' -__build__ = 0x00007e +__version__ = '0.11.4' +__build__ = 0x00007f __author__ = 'Artur Barseghyan ' __copyright__ = '2014-2017 Artur Barseghyan' __license__ = 'GPL 2.0/LGPL 2.1' diff --git a/src/fobi/contrib/apps/drf_integration/README.rst b/src/fobi/contrib/apps/drf_integration/README.rst index 21937bec..c56e8f29 100644 --- a/src/fobi/contrib/apps/drf_integration/README.rst +++ b/src/fobi/contrib/apps/drf_integration/README.rst @@ -19,6 +19,14 @@ Supported fields ---------------- The following fields are supported. +Content +~~~~~~~ +- content_image +- content_text +- content_video + +Fields +~~~~~~ - boolean - checkbox_select_multiple - date @@ -52,9 +60,6 @@ The following fields are not supported. Those marked with asterisk are planned to be supported in the upcoming releases. - date_drop_down -- content_image -- content_text -- content_video - select_model_object - select_mptt_model_object - select_multiple_model_objects @@ -309,5 +314,4 @@ or use plain Django tests: Limitations ----------- -Due to limits of the API interface, certain fields are not available -yet (presentational fields). +Certain fields are not available yet (relational fields). diff --git a/src/fobi/contrib/apps/drf_integration/TODOS.rst b/src/fobi/contrib/apps/drf_integration/TODOS.rst index 2259950c..836dd3d1 100644 --- a/src/fobi/contrib/apps/drf_integration/TODOS.rst +++ b/src/fobi/contrib/apps/drf_integration/TODOS.rst @@ -27,14 +27,16 @@ Must haves + Fixed Python3 issues with max_length for text fields. + In decimal plugin, if any of the values are None, don't try to cast them into Decimal. -- Add ``date_drop_down`` plugin. ++ Fix this https://github.com/barseghyanartur/django-fobi/blob/master/src/fobi/contrib/apps/drf_integration/views.py#L151 + It should not be form = ... but serializer = ... Should haves ------------ + Find why HiddenInput tests fail (in terms of Django REST framework it's a read-only field). -- Add Integration form callbacks for handling data of the integration plugins. -- Add more fields (relation- and presentational- fields). ++ Add Integration form callbacks for handling data of the integration plugins. +- Add ``date_drop_down`` plugin. +- Add more fields (relation fields). - Think of what to do with presentational fields (perhaps just display?) - Somehow, the ``file`` plugin data, when submitted, isn't shown properly in the posted data (by DRF), although is posted 100% correctly. @@ -47,4 +49,4 @@ Could haves Would haves ----------- -- Remove codebin.py at the end. ++ Remove codebin.py at the end. diff --git a/src/fobi/contrib/apps/drf_integration/fields.py b/src/fobi/contrib/apps/drf_integration/fields.py index fda3bac7..c2308ebd 100644 --- a/src/fobi/contrib/apps/drf_integration/fields.py +++ b/src/fobi/contrib/apps/drf_integration/fields.py @@ -1,13 +1,13 @@ import copy -# import six -# -# from django.utils.safestring import mark_safe +import six + +from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ from rest_framework.fields import ( - # Field, - # empty, + Field, + empty, MultipleChoiceField, ) @@ -16,7 +16,11 @@ __author__ = 'Artur Barseghyan ' __copyright__ = '2016-2017 Artur Barseghyan' __license__ = 'GPL 2.0/LGPL 2.1' __all__ = ( + 'ContentImageField', + 'ContentTextField', + 'ContentVideoField', 'MultipleChoiceWithMaxField', + 'NoneField', ) @@ -43,3 +47,49 @@ class MultipleChoiceWithMaxField(MultipleChoiceField): MultipleChoiceWithMaxField, self ).to_internal_value(data) + + +class NoneField(Field): + """NoneField.""" + + default_error_messages = {} + initial = '' + default_empty_html = '' + + def __init__(self, **kwargs): + self.allow_blank = True + self.trim_whitespace = kwargs.pop('trim_whitespace', True) + self.raw_data = kwargs.pop('raw_data', {}) + super(NoneField, self).__init__(**kwargs) + + def run_validation(self, data=empty): + return '' + + def to_internal_value(self, data): + # We're lenient with allowing basic numerics to be coerced into + # strings, but other types should fail. Eg. unclear if booleans + # should represent as `true` or `True`, and composites such as lists + # are likely user error. + _not_isinstance_str_int_float = not isinstance( + data, six.string_types + six.integer_types + (float,) + ) + if isinstance(data, bool) or _not_isinstance_str_int_float: + self.fail('invalid') + value = six.text_type(data) + return value.strip() if self.trim_whitespace else value + + def to_representation(self, value): + return mark_safe(six.text_type(value)) + + +class ContentTextField(NoneField): + """Content text field.""" + + +class ContentImageField(NoneField): + """Content image field.""" + + +class ContentVideoField(NoneField): + """Content video field.""" + diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/content/__init__.py b/src/fobi/contrib/apps/drf_integration/form_elements/content/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/README.rst b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/README.rst new file mode 100644 index 00000000..6f8fd00b --- /dev/null +++ b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/README.rst @@ -0,0 +1,28 @@ +==================================================================== +fobi.contrib.apps.drf_integration.form_elements.fields.content_image +==================================================================== +A ``django-fobi`` ContentImage plugin for integration with +``Django REST framework``. Makes use of the +``fobi.contrib.apps.drf_integration.fields.ContentImage``. + +Installation +============ +1. Add ``fobi.contrib.apps.drf_integration.form_elements.fields.content_image`` + to the ``INSTALLED_APPS`` in your ``settings.py``. + +.. code-block:: python + + INSTALLED_APPS = ( + # ... + 'fobi.contrib.apps.drf_integration.form_elements.fields.content_image', + # ... + ) + +2. In the terminal type: + +.. code-block:: sh + + ./manage.py fobi_sync_plugins + +3. Assign appropriate permissions to the target users/groups to be using + the plugin if ``FOBI_RESTRICT_PLUGIN_ACCESS`` is set to True. diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/__init__.py b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/__init__.py new file mode 100644 index 00000000..cddce2c0 --- /dev/null +++ b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/__init__.py @@ -0,0 +1,11 @@ +__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \ + 'content_image' +__author__ = 'Artur Barseghyan ' +__copyright__ = '2014-2017 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' +__all__ = ('default_app_config', 'UID',) + +default_app_config = 'fobi.contrib.apps.drf_integration.form_elements.' \ + 'content.content_image.apps.Config' + +UID = 'content_image' diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/apps.py b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/apps.py new file mode 100644 index 00000000..a952435a --- /dev/null +++ b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/apps.py @@ -0,0 +1,19 @@ +__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \ + 'content_image.apps' +__author__ = 'Artur Barseghyan ' +__copyright__ = '2014-2017 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' + +try: + __all__ = ('Config',) + + from django.apps import AppConfig + + class Config(AppConfig): + name = 'fobi.contrib.apps.drf_integration.form_elements.content.' \ + 'content_image' + label = 'fobi_contrib_apps_drf_integration_form_elements_content_' \ + 'content_image' + +except ImportError: + pass diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/base.py b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/base.py new file mode 100644 index 00000000..50e4c89d --- /dev/null +++ b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/base.py @@ -0,0 +1,59 @@ +import logging + +from django.utils.translation import ugettext_lazy as _ + +from .......base import IntegrationFormElementPlugin +from .... import UID as INTEGRATE_WITH_UID +from ....base import ( + DRFIntegrationFormElementPluginProcessor, + DRFSubmitPluginFormDataMixin, +) +from ....fields import ContentImageField +from . import UID + +__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \ + 'content_image.base' +__author__ = 'Artur Barseghyan ' +__copyright__ = '2014-2017 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' +__all__ = ('ContentImagePlugin',) + + +LOGGER = logging.getLogger(__name__) + + +class ContentImagePlugin(IntegrationFormElementPlugin, + DRFSubmitPluginFormDataMixin): + """CharField plugin.""" + + uid = UID + integrate_with = INTEGRATE_WITH_UID + name = _("Content image") + group = _("Content") + + def get_custom_field_instances(self, + form_element_plugin, + request=None, + form_entry=None, + form_element_entries=None, + has_value=None, + **kwargs): + """Get form field instances.""" + + rendered_image = form_element_plugin.get_rendered_image() + + field_kwargs = { + 'initial': rendered_image, + 'default': rendered_image, + 'required': False, + 'label': '', + 'read_only': True, + 'raw_data': form_element_plugin.get_raw_data(), + } + + return [ + DRFIntegrationFormElementPluginProcessor( + field_class=ContentImageField, + field_kwargs=field_kwargs + ) + ] diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/fobi_integration_form_elements.py b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/fobi_integration_form_elements.py new file mode 100644 index 00000000..3cad572c --- /dev/null +++ b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_image/fobi_integration_form_elements.py @@ -0,0 +1,12 @@ +from .......base import integration_form_element_plugin_registry +from .base import ContentImagePlugin + +__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \ + 'content_image.fobi_integration_form_elements' +__author__ = 'Artur Barseghyan ' +__copyright__ = '2014-2017 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' +__all__ = ('ContentImagePlugin',) + + +integration_form_element_plugin_registry.register(ContentImagePlugin) diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/README.rst b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/README.rst new file mode 100644 index 00000000..6791460b --- /dev/null +++ b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/README.rst @@ -0,0 +1,28 @@ +=================================================================== +fobi.contrib.apps.drf_integration.form_elements.fields.content_text +=================================================================== +A ``django-fobi`` ContentText plugin for integration with +``Django REST framework``. Makes use of the +``fobi.contrib.apps.drf_integration.fields.ContentText``. + +Installation +============ +1. Add ``fobi.contrib.apps.drf_integration.form_elements.fields.content_text`` + to the ``INSTALLED_APPS`` in your ``settings.py``. + +.. code-block:: python + + INSTALLED_APPS = ( + # ... + 'fobi.contrib.apps.drf_integration.form_elements.fields.content_text', + # ... + ) + +2. In the terminal type: + +.. code-block:: sh + + ./manage.py fobi_sync_plugins + +3. Assign appropriate permissions to the target users/groups to be using + the plugin if ``FOBI_RESTRICT_PLUGIN_ACCESS`` is set to True. diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/__init__.py b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/__init__.py new file mode 100644 index 00000000..993d182a --- /dev/null +++ b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/__init__.py @@ -0,0 +1,11 @@ +__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \ + 'content_text' +__author__ = 'Artur Barseghyan ' +__copyright__ = '2014-2017 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' +__all__ = ('default_app_config', 'UID',) + +default_app_config = 'fobi.contrib.apps.drf_integration.form_elements.' \ + 'content.content_text.apps.Config' + +UID = 'content_text' diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/apps.py b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/apps.py new file mode 100644 index 00000000..9cc20ee3 --- /dev/null +++ b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/apps.py @@ -0,0 +1,19 @@ +__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \ + 'content_text.apps' +__author__ = 'Artur Barseghyan ' +__copyright__ = '2014-2017 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' + +try: + __all__ = ('Config',) + + from django.apps import AppConfig + + class Config(AppConfig): + name = 'fobi.contrib.apps.drf_integration.form_elements.content.' \ + 'content_text' + label = 'fobi_contrib_apps_drf_integration_form_elements_content_' \ + 'content_text' + +except ImportError: + pass diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/base.py b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/base.py new file mode 100644 index 00000000..085395b9 --- /dev/null +++ b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/base.py @@ -0,0 +1,61 @@ +import logging + +from django.utils.translation import ugettext_lazy as _ + +from .......base import IntegrationFormElementPlugin +from .... import UID as INTEGRATE_WITH_UID +from ....base import ( + DRFIntegrationFormElementPluginProcessor, + DRFSubmitPluginFormDataMixin, +) +from ....fields import ContentTextField +from . import UID + +__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \ + 'content_text.base' +__author__ = 'Artur Barseghyan ' +__copyright__ = '2014-2017 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' +__all__ = ('ContentTextPlugin',) + + +LOGGER = logging.getLogger(__name__) + + +class ContentTextPlugin(IntegrationFormElementPlugin, + DRFSubmitPluginFormDataMixin): + """CharField plugin.""" + + uid = UID + integrate_with = INTEGRATE_WITH_UID + name = _("Content text") + group = _("Content") + + def get_custom_field_instances(self, + form_element_plugin, + request=None, + form_entry=None, + form_element_entries=None, + has_value=None, + **kwargs): + """Get form field instances.""" + + rendered_text = form_element_plugin.get_rendered_text() + + LOGGER.debug(rendered_text) + + field_kwargs = { + 'initial': rendered_text, + 'default': rendered_text, + 'required': False, + 'label': '', + 'read_only': True, + 'raw_data': form_element_plugin.get_raw_data(), + } + + return [ + DRFIntegrationFormElementPluginProcessor( + field_class=ContentTextField, + field_kwargs=field_kwargs + ) + ] diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/fobi_integration_form_elements.py b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/fobi_integration_form_elements.py new file mode 100644 index 00000000..55520d13 --- /dev/null +++ b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_text/fobi_integration_form_elements.py @@ -0,0 +1,12 @@ +from .......base import integration_form_element_plugin_registry +from .base import ContentTextPlugin + +__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \ + 'content_text.fobi_integration_form_elements' +__author__ = 'Artur Barseghyan ' +__copyright__ = '2014-2017 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' +__all__ = ('ContentTextPlugin',) + + +integration_form_element_plugin_registry.register(ContentTextPlugin) diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/README.rst b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/README.rst new file mode 100644 index 00000000..1028ed68 --- /dev/null +++ b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/README.rst @@ -0,0 +1,28 @@ +==================================================================== +fobi.contrib.apps.drf_integration.form_elements.fields.content_video +==================================================================== +A ``django-fobi`` ContentVideo plugin for integration with +``Django REST framework``. Makes use of the +``fobi.contrib.apps.drf_integration.fields.ContentVideo``. + +Installation +============ +1. Add ``fobi.contrib.apps.drf_integration.form_elements.fields.content_video`` + to the ``INSTALLED_APPS`` in your ``settings.py``. + +.. code-block:: python + + INSTALLED_APPS = ( + # ... + 'fobi.contrib.apps.drf_integration.form_elements.fields.content_video', + # ... + ) + +2. In the terminal type: + +.. code-block:: sh + + ./manage.py fobi_sync_plugins + +3. Assign appropriate permissions to the target users/groups to be using + the plugin if ``FOBI_RESTRICT_PLUGIN_ACCESS`` is set to True. diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/__init__.py b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/__init__.py new file mode 100644 index 00000000..78be309b --- /dev/null +++ b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/__init__.py @@ -0,0 +1,11 @@ +__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \ + 'content_video' +__author__ = 'Artur Barseghyan ' +__copyright__ = '2014-2017 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' +__all__ = ('default_app_config', 'UID',) + +default_app_config = 'fobi.contrib.apps.drf_integration.form_elements.' \ + 'content.content_video.apps.Config' + +UID = 'content_video' diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/apps.py b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/apps.py new file mode 100644 index 00000000..c7142224 --- /dev/null +++ b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/apps.py @@ -0,0 +1,19 @@ +__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \ + 'content_video.apps' +__author__ = 'Artur Barseghyan ' +__copyright__ = '2014-2017 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' + +try: + __all__ = ('Config',) + + from django.apps import AppConfig + + class Config(AppConfig): + name = 'fobi.contrib.apps.drf_integration.form_elements.content.' \ + 'content_video' + label = 'fobi_contrib_apps_drf_integration_form_elements_content_' \ + 'content_video' + +except ImportError: + pass diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/base.py b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/base.py new file mode 100644 index 00000000..612cb124 --- /dev/null +++ b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/base.py @@ -0,0 +1,58 @@ +import logging + +from django.utils.translation import ugettext_lazy as _ + +from .......base import IntegrationFormElementPlugin +from .... import UID as INTEGRATE_WITH_UID +from ....base import ( + DRFIntegrationFormElementPluginProcessor, + DRFSubmitPluginFormDataMixin, +) +from ....fields import ContentVideoField +from . import UID + +__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \ + 'content_video.base' +__author__ = 'Artur Barseghyan ' +__copyright__ = '2014-2017 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' +__all__ = ('ContentVideoPlugin',) + + +LOGGER = logging.getLogger(__name__) + + +class ContentVideoPlugin(IntegrationFormElementPlugin, + DRFSubmitPluginFormDataMixin): + """CharField plugin.""" + + uid = UID + integrate_with = INTEGRATE_WITH_UID + name = _("Content image") + group = _("Content") + + def get_custom_field_instances(self, + form_element_plugin, + request=None, + form_entry=None, + form_element_entries=None, + has_value=None, + **kwargs): + """Get form field instances.""" + rendered_video = form_element_plugin.get_rendered_video() + + field_kwargs = { + 'initial': rendered_video, + 'default': rendered_video, + 'required': False, + 'label': '', + 'read_only': True, + 'raw_data': form_element_plugin.get_raw_data(), + } + + return [ + DRFIntegrationFormElementPluginProcessor( + field_class=ContentVideoField, + field_kwargs=field_kwargs + ) + ] diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/fobi_integration_form_elements.py b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/fobi_integration_form_elements.py new file mode 100644 index 00000000..70b9a1fe --- /dev/null +++ b/src/fobi/contrib/apps/drf_integration/form_elements/content/content_video/fobi_integration_form_elements.py @@ -0,0 +1,12 @@ +from .......base import integration_form_element_plugin_registry +from .base import ContentVideoPlugin + +__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \ + 'content_video.fobi_integration_form_elements' +__author__ = 'Artur Barseghyan ' +__copyright__ = '2014-2017 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' +__all__ = ('ContentVideoPlugin',) + + +integration_form_element_plugin_registry.register(ContentVideoPlugin) diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/fields/decimal/README.rst b/src/fobi/contrib/apps/drf_integration/form_elements/fields/decimal/README.rst index 45248f5c..161e75ac 100644 --- a/src/fobi/contrib/apps/drf_integration/form_elements/fields/decimal/README.rst +++ b/src/fobi/contrib/apps/drf_integration/form_elements/fields/decimal/README.rst @@ -1,20 +1,20 @@ -=============================================================== -fobi.contrib.apps.drf_integration.form_elements.fields.datetime -=============================================================== +============================================================== +fobi.contrib.apps.drf_integration.form_elements.fields.decimal +============================================================== A ``django-fobi`` DecimalField plugin for integration with ``Django REST framework``. Makes use of the -``rest_framework.fields.DateTimeField``. +``rest_framework.fields.DecimalField``. Installation ============ -1. Add ``fobi.contrib.apps.drf_integration.form_elements.fields.datetime`` to +1. Add ``fobi.contrib.apps.drf_integration.form_elements.fields.decimal`` to the ``INSTALLED_APPS`` in your ``settings.py``. .. code-block:: python INSTALLED_APPS = ( # ... - 'fobi.contrib.apps.drf_integration.form_elements.fields.datetime', + 'fobi.contrib.apps.drf_integration.form_elements.fields.decimal', # ... ) diff --git a/src/fobi/contrib/apps/drf_integration/metadata.py b/src/fobi/contrib/apps/drf_integration/metadata.py new file mode 100644 index 00000000..2d241567 --- /dev/null +++ b/src/fobi/contrib/apps/drf_integration/metadata.py @@ -0,0 +1,60 @@ +import copy + +from rest_framework.metadata import SimpleMetadata +from rest_framework.utils.field_mapping import ClassLookupDict + +from .fields import ( + MultipleChoiceWithMaxField, + ContentImageField, + ContentTextField, + ContentVideoField, +) + +__title__ = 'fobi.contrib.apps.drf_integration.metadata' +__author__ = 'Artur Barseghyan ' +__copyright__ = '2016-2017 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' +__all__ = ( + 'FobiMetaData', +) + + +class FobiMetaData(SimpleMetadata): + """Meta data for better representation of the form elements.""" + + __mapping = copy.copy(SimpleMetadata.label_lookup.mapping)\ + + __mapping.update( + { + MultipleChoiceWithMaxField: 'multiple choice', + ContentTextField: 'content', + } + ) + + label_lookup = ClassLookupDict(__mapping) + + def get_field_info(self, field): + """ + Given an instance of a serializer field, return a dictionary + of metadata about it. + """ + field_info = super(FobiMetaData, self).get_field_info(field) + if isinstance( + field, + (ContentTextField, ContentImageField, ContentVideoField) + ): + field_info['type'] = 'content' + + if isinstance(field, ContentTextField): + field_info['contenttype'] = 'text' + field_info['content'] = field.initial + field_info['raw'] = field.raw_data + elif isinstance(field, ContentImageField): + field_info['contenttype'] = 'image' + field_info['content'] = field.initial + field_info['raw'] = field.raw_data + else: + field_info['contenttype'] = 'video' + field_info['content'] = field.initial + field_info['raw'] = field.raw_data + return field_info diff --git a/src/fobi/contrib/apps/drf_integration/views.py b/src/fobi/contrib/apps/drf_integration/views.py index 0a832502..fb2335a1 100644 --- a/src/fobi/contrib/apps/drf_integration/views.py +++ b/src/fobi/contrib/apps/drf_integration/views.py @@ -22,6 +22,7 @@ from .base import ( submit_plugin_form_data, ) from .dynamic import get_declared_fields +from .metadata import FobiMetaData from .serializers import FormEntrySerializer from .utils import get_serializer_class @@ -52,6 +53,7 @@ class FobiFormEntryViewSet( permission_classes = [permissions.AllowAny] lookup_field = 'slug' lookup_url_kwarg = 'slug' + metadata_class = FobiMetaData def has_value(self): return None if self.action == 'metadata' else True @@ -148,7 +150,7 @@ class FobiFormEntryViewSet( form_element_entries = form_entry.formelemententry_set.all() # Fire form valid before submit plugin data - form = fire_form_callbacks( + serializer = fire_form_callbacks( form_entry=form_entry, request=request, serializer=serializer, @@ -162,8 +164,8 @@ class FobiFormEntryViewSet( serializer=serializer ) - # # Fire form valid callbacks - form = fire_form_callbacks( + # Fire form valid callbacks + serializer = fire_form_callbacks( form_entry=form_entry, request=request, serializer=serializer, diff --git a/src/fobi/contrib/plugins/form_elements/content/content_image/base.py b/src/fobi/contrib/plugins/form_elements/content/content_image/base.py index 8bd854af..30dbdcd9 100644 --- a/src/fobi/contrib/plugins/form_elements/content/content_image/base.py +++ b/src/fobi/contrib/plugins/form_elements/content/content_image/base.py @@ -1,5 +1,6 @@ from __future__ import absolute_import +from collections import OrderedDict from uuid import uuid4 from django.conf import settings @@ -56,6 +57,20 @@ class ContentImagePlugin(FormElementPlugin): ) return self.get_cloned_plugin_data(update={'file': cloned_image}) + def get_raw_data(self): + """Get raw data. + + Might be used in integration plugins. + """ + return OrderedDict( + ( + ('file', "{}{}".format(settings.MEDIA_URL, self.data.file)), + ('alt', self.data.alt), + ('fit_method', self.data.fit_method), + ('size', self.data.size), + ) + ) + def get_rendered_image(self): """Get rendered image.""" width, height = self.data.size.split('x') diff --git a/src/fobi/contrib/plugins/form_elements/content/content_text/base.py b/src/fobi/contrib/plugins/form_elements/content/content_text/base.py index 2188c353..984dfe8e 100644 --- a/src/fobi/contrib/plugins/form_elements/content/content_text/base.py +++ b/src/fobi/contrib/plugins/form_elements/content/content_text/base.py @@ -1,7 +1,9 @@ from __future__ import absolute_import +from collections import OrderedDict from uuid import uuid4 +from django.template.loader import render_to_string from django.utils.encoding import smart_str from django.utils.translation import ugettext_lazy as _ @@ -34,6 +36,26 @@ class ContentTextPlugin(FormElementPlugin): """ self.data.name = "{0}_{1}".format(self.uid, uuid4()) + def get_raw_data(self): + """Get raw data. + + Might be used in integration plugins. + """ + return OrderedDict( + ( + ('text', self.data.text), + ) + ) + + def get_rendered_text(self): + """Get rendered image.""" + + context = { + 'plugin': self, + } + rendered_text = render_to_string('content_image/render.html', context) + return rendered_text + def get_form_field_instances(self, request=None, form_entry=None, form_element_entries=None, **kwargs): """Get form field instances.""" diff --git a/src/fobi/contrib/plugins/form_elements/content/content_video/base.py b/src/fobi/contrib/plugins/form_elements/content/content_video/base.py index 3177aae4..f7dd869d 100644 --- a/src/fobi/contrib/plugins/form_elements/content/content_video/base.py +++ b/src/fobi/contrib/plugins/form_elements/content/content_video/base.py @@ -1,5 +1,6 @@ from __future__ import absolute_import +from collections import OrderedDict from uuid import uuid4 from django.utils.translation import ugettext_lazy as _ @@ -35,14 +36,33 @@ class ContentVideoPlugin(FormElementPlugin): """ self.data.name = "{0}_{1}".format(self.uid, uuid4()) + def get_raw_data(self): + """Get raw data. + + Might be used in integration plugins. + """ + return OrderedDict( + ( + ('title', self.data.title), + ('url', self.data.url), + ('size', self.data.size), + ) + ) + + def get_rendered_video(self): + """Get rendered video. + + Might be used in integration plugins. + """ + width, height = self.data.size.split('x') + return render_video(self.data.url, width, height) + def get_form_field_instances(self, request=None, form_entry=None, form_element_entries=None, **kwargs): """Get form field instances.""" - width, height = self.data.size.split('x') - field_kwargs = { 'initial': '
{0}
'.format( - render_video(self.data.url, width, height) + self.get_rendered_video() ), 'required': False, 'label': '', From 4156f96eb6049d97d8592d119be795e34f797a86 Mon Sep 17 00:00:00 2001 From: Artur Barseghyan Date: Fri, 12 May 2017 00:56:18 +0200 Subject: [PATCH 6/7] clean up --- src/fobi/contrib/apps/drf_integration/metadata.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/fobi/contrib/apps/drf_integration/metadata.py b/src/fobi/contrib/apps/drf_integration/metadata.py index 2d241567..c1460b1e 100644 --- a/src/fobi/contrib/apps/drf_integration/metadata.py +++ b/src/fobi/contrib/apps/drf_integration/metadata.py @@ -22,19 +22,21 @@ __all__ = ( class FobiMetaData(SimpleMetadata): """Meta data for better representation of the form elements.""" - __mapping = copy.copy(SimpleMetadata.label_lookup.mapping)\ - + __mapping = copy.copy(SimpleMetadata.label_lookup.mapping) __mapping.update( { MultipleChoiceWithMaxField: 'multiple choice', + ContentImageField: 'content', ContentTextField: 'content', + ContentVideoField: 'content', } ) label_lookup = ClassLookupDict(__mapping) def get_field_info(self, field): - """ + """Get field info. + Given an instance of a serializer field, return a dictionary of metadata about it. """ @@ -57,4 +59,5 @@ class FobiMetaData(SimpleMetadata): field_info['contenttype'] = 'video' field_info['content'] = field.initial field_info['raw'] = field.raw_data + return field_info From 19592c1567c8c70a709f212db49e5b4dd6a4e43b Mon Sep 17 00:00:00 2001 From: Artur Barseghyan Date: Fri, 12 May 2017 03:10:00 +0200 Subject: [PATCH 7/7] docs updated --- examples/simple/settings/base.py | 6 ++++++ .../contrib/apps/drf_integration/README.rst | 17 ++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/examples/simple/settings/base.py b/examples/simple/settings/base.py index 09d017c7..5098395f 100644 --- a/examples/simple/settings/base.py +++ b/examples/simple/settings/base.py @@ -468,6 +468,12 @@ PACKAGE_NAME_GRAPPELLI = "grappelli_safe" # Just for tests # } # SOUTH_MIGRATION_MODULES = 'south_migrations' +# ************************************************************** +# ********************* Registration settings ****************** +# ************************************************************** + +ACCOUNT_ACTIVATION_DAYS = 7 + # ************************************************************** # ************************ Fobi settings *********************** # ************************************************************** diff --git a/src/fobi/contrib/apps/drf_integration/README.rst b/src/fobi/contrib/apps/drf_integration/README.rst index c56e8f29..bb971781 100644 --- a/src/fobi/contrib/apps/drf_integration/README.rst +++ b/src/fobi/contrib/apps/drf_integration/README.rst @@ -19,8 +19,8 @@ Supported fields ---------------- The following fields are supported. -Content -~~~~~~~ +Content (presentational form elements) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - content_image - content_text - content_video @@ -105,6 +105,9 @@ the core plugins: - fobi.contrib.plugins.form_elements.fields.textarea - fobi.contrib.plugins.form_elements.fields.time - fobi.contrib.plugins.form_elements.fields.url +- fobi.contrib.plugins.form_elements.content.content_image +- fobi.contrib.plugins.form_elements.content.content_text +- fobi.contrib.plugins.form_elements.content.content_video - fobi.contrib.plugins.form_handlers.db_store - fobi.contrib.plugins.form_handlers.http_repost - fobi.contrib.plugins.form_handlers.mail @@ -138,6 +141,9 @@ in the ``INSTALLED_APPS`` as well: - fobi.contrib.apps.drf_integration.form_elements.fields.textarea - fobi.contrib.apps.drf_integration.form_elements.fields.time - fobi.contrib.apps.drf_integration.form_elements.fields.url +- fobi.contrib.apps.drf_integration.form_elements.content.content_image +- fobi.contrib.apps.drf_integration.form_elements.content.content_text +- fobi.contrib.apps.drf_integration.form_elements.content.content_video - fobi.contrib.apps.drf_integration.form_handlers.db_store - fobi.contrib.apps.drf_integration.form_handlers.http_repost - fobi.contrib.apps.drf_integration.form_handlers.mail @@ -170,7 +176,7 @@ See the `example settings file 'rest_framework', # Django REST framework 'fobi.contrib.apps.drf_integration', # DRF integration app - # DRF integration form element plugins + # DRF integration form element plugins - fields 'fobi.contrib.apps.drf_integration.form_elements.fields.boolean', 'fobi.contrib.apps.drf_integration.form_elements.fields.checkbox_select_multiple', 'fobi.contrib.apps.drf_integration.form_elements.fields.date', @@ -198,6 +204,11 @@ See the `example settings file 'fobi.contrib.apps.drf_integration.form_elements.fields.time', 'fobi.contrib.apps.drf_integration.form_elements.fields.url', + # DRF integration form element plugins - presentational + 'fobi.contrib.apps.drf_integration.form_elements.content.content_image', + 'fobi.contrib.apps.drf_integration.form_elements.content.content_text', + 'fobi.contrib.apps.drf_integration.form_elements.content.content_video', + # DRF integration form handler plugins 'fobi.contrib.apps.drf_integration.form_handlers.db_store', 'fobi.contrib.apps.drf_integration.form_handlers.mail',