def _edit_form_attr(request, domain, app_id, form_unique_id, attr): """ Called to edit any (supported) form attribute, given by attr """ ajax = json.loads(request.POST.get('ajax', 'true')) resp = {} app = get_app(domain, app_id) try: form = app.get_form(form_unique_id) except FormNotFoundException as e: if ajax: return HttpResponseBadRequest(str(e)) else: messages.error(request, _("There was an error saving, please try again!")) return back_to_main(request, domain, app_id=app_id) lang = request.COOKIES.get('lang', app.langs[0]) def should_edit(attribute): return attribute in request.POST if 'sha1' in request.POST and (should_edit("xform") or "xform" in request.FILES): conflict = _get_xform_conflict_response(form, request.POST['sha1']) if conflict is not None: return conflict if should_edit("name"): name = request.POST['name'] form.name[lang] = name if not form.form_type == "shadow_form": xform = form.wrapped_xform() if xform.exists(): xform.set_name(name) save_xform(app, form, xform.render()) resp['update'] = {'.variable-form_name': clean_trans(form.name, [lang])} if should_edit('comment'): form.comment = request.POST['comment'] if should_edit("xform") or "xform" in request.FILES: try: # support FILES for upload and POST for ajax post from Vellum try: xform = request.FILES.get('xform').read() except Exception: xform = request.POST.get('xform') else: try: xform = str(xform, encoding="utf-8") except Exception: raise Exception("Error uploading form: Please make sure your form is encoded in UTF-8") if request.POST.get('cleanup', False): try: # First, we strip all newlines and reformat the DOM. px = parseString(xform.replace('\r\n', '')).toprettyxml() # Then we remove excess newlines from the DOM output. text_re = re.compile(r'>\n\s+([^<>\s].*?)\n\s+</', re.DOTALL) prettyXml = text_re.sub(r'>\g<1></', px) xform = prettyXml except Exception: pass if xform: if isinstance(xform, str): xform = xform.encode('utf-8') save_xform(app, form, xform) else: raise Exception("You didn't select a form to upload") except Exception as e: notify_exception(request, str(e)) if ajax: return HttpResponseBadRequest(str(e)) else: messages.error(request, str(e)) if should_edit("references") or should_edit("case_references"): form.case_references = _get_case_references(request.POST) if should_edit("show_count"): show_count = request.POST['show_count'] form.show_count = True if show_count == "True" else False if should_edit("put_in_root"): put_in_root = request.POST['put_in_root'] form.put_in_root = True if put_in_root == "True" else False if should_edit('form_filter'): form.form_filter = request.POST['form_filter'] if should_edit('post_form_workflow'): form.post_form_workflow = request.POST['post_form_workflow'] if should_edit('auto_gps_capture'): form.auto_gps_capture = request.POST['auto_gps_capture'] == 'true' if should_edit('is_release_notes_form'): form.is_release_notes_form = request.POST['is_release_notes_form'] == 'true' if should_edit('enable_release_notes'): form.enable_release_notes = request.POST['enable_release_notes'] == 'true' if not form.is_release_notes_form and form.enable_release_notes: return json_response( {'message': _("You can't enable a form as release notes without allowing it as " "a release notes form <TODO messaging>")}, status_code=400 ) if (should_edit("form_links_xpath_expressions") and should_edit("form_links_form_ids") and toggles.FORM_LINK_WORKFLOW.enabled(domain)): form_links = zip( request.POST.getlist('form_links_xpath_expressions'), request.POST.getlist('form_links_form_ids'), [ json.loads(datum_json) if datum_json else [] for datum_json in request.POST.getlist('datums_json') ], ) module_unique_ids = [m.unique_id for m in app.get_modules()] form.form_links = [FormLink( xpath=link[0], form_id=link[1] if link[1] not in module_unique_ids else None, module_unique_id=link[1] if link[1] in module_unique_ids else None, datums=[ FormDatum(name=datum['name'], xpath=datum['xpath']) for datum in link[2] ] ) for link in form_links] if should_edit('post_form_workflow_fallback'): form.post_form_workflow_fallback = request.POST.get('post_form_workflow_fallback') if should_edit('custom_instances'): instances = json.loads(request.POST.get('custom_instances')) try: # validate that custom instances can be added into the XML for instance in instances: etree.fromstring( "<instance id='{}' src='{}' />".format( instance.get('instanceId'), instance.get('instancePath') ) ) except etree.XMLSyntaxError as error: return json_response( {'message': _("There was an issue with your custom instances: {}").format(error)}, status_code=400 ) form.custom_instances = [ CustomInstance( instance_id=instance.get("instanceId"), instance_path=instance.get("instancePath"), ) for instance in instances ] if should_edit('custom_assertions'): assertions = json.loads(request.POST.get('custom_assertions')) try: # validate that custom assertions can be added into the XML for assertion in assertions: etree.fromstring( '<assertion test="{test}"><text><locale id="abc.def"/>{text}</text></assertion>'.format( **assertion ) ) except etree.XMLSyntaxError as error: return json_response( {'message': _("There was an issue with your custom assertions: {}").format(error)}, status_code=400 ) existing_assertions = {assertion.test: assertion for assertion in form.custom_assertions} new_assertions = [] for assertion in assertions: try: new_assertion = existing_assertions[assertion.get('test')] new_assertion.text[lang] = assertion.get('text') except KeyError: new_assertion = CustomAssertion( test=assertion.get('test'), text={lang: assertion.get('text')} ) new_assertions.append(new_assertion) form.custom_assertions = new_assertions if should_edit("shadow_parent"): form.shadow_parent_form_id = request.POST['shadow_parent'] if should_edit("custom_icon_form"): error_message = handle_custom_icon_edits(request, form, lang) if error_message: return json_response( {'message': error_message}, status_code=400 ) if should_edit('session_endpoint_id'): raw_endpoint_id = request.POST['session_endpoint_id'] try: set_session_endpoint(form, raw_endpoint_id, app) except InvalidSessionEndpoint as e: return json_response({'message': str(e)}, status_code=400) if should_edit('function_datum_endpoints'): if request.POST['function_datum_endpoints']: form.function_datum_endpoints = request.POST['function_datum_endpoints'].replace(" ", "").split(",") else: form.function_datum_endpoints = [] handle_media_edits(request, form, should_edit, resp, lang) app.save(resp) notify_form_changed(domain, request.couch_user, app_id, form_unique_id) if ajax: return HttpResponse(json.dumps(resp)) else: return back_to_main(request, domain, app_id=app_id, form_unique_id=form_unique_id)
def edit_module_attr(request, domain, app_id, module_unique_id, attr): """ Called to edit any (supported) module attribute, given by attr """ attributes = { "all": None, "auto_select_case": None, "case_list": ('case_list-show', 'case_list-label'), "case_list-menu_item_media_audio": None, "case_list-menu_item_media_image": None, "case_list_form_id": None, "case_list_form_label": None, "case_list_form_media_audio": None, "case_list_form_media_image": None, "case_list_post_form_workflow": None, "case_type": None, 'comment': None, "display_separately": None, "has_schedule": None, "media_audio": None, "media_image": None, "module_filter": None, "name": None, "parent_module": None, "put_in_root": None, "root_module_id": None, "source_module_id": None, "task_list": ('task_list-show', 'task_list-label'), "excl_form_ids": None, "display_style": None, "custom_icon_form": None, "custom_icon_text_body": None, "custom_icon_xpath": None, "use_default_image_for_all": None, "use_default_audio_for_all": None, } if attr not in attributes: return HttpResponseBadRequest() def should_edit(attribute): if attribute == attr: return True if 'all' == attr: if attributes[attribute]: for param in attributes[attribute]: if not request.POST.get(param): return False return True else: return request.POST.get(attribute) is not None app = get_app(domain, app_id) try: module = app.get_module_by_unique_id(module_unique_id) except ModuleNotFoundException: # temporary fallback module = app.get_module(module_unique_id) lang = request.COOKIES.get('lang', app.langs[0]) resp = {'update': {}, 'corrections': {}} if should_edit("custom_icon_form"): error_message = handle_custom_icon_edits(request, module, lang) if error_message: return json_response({'message': error_message}, status_code=400) if should_edit("case_type"): case_type = request.POST.get("case_type", None) if case_type == USERCASE_TYPE and not isinstance( module, AdvancedModule): return HttpResponseBadRequest( '"{}" is a reserved case type'.format(USERCASE_TYPE)) elif case_type and not is_valid_case_type(case_type, module): return HttpResponseBadRequest("case type is improperly formatted") else: old_case_type = module["case_type"] module["case_type"] = case_type # rename other reference to the old case type all_advanced_modules = [] modules_with_old_case_type_exist = False for mod in app.modules: if isinstance(mod, AdvancedModule): all_advanced_modules.append(mod) modules_with_old_case_type_exist |= mod.case_type == old_case_type for mod in all_advanced_modules: for form in mod.forms: for action in form.actions.get_load_update_actions(): if action.case_type == old_case_type and action.details_module == module_unique_id: action.case_type = case_type if mod.unique_id == module_unique_id or not modules_with_old_case_type_exist: for action in form.actions.get_open_actions(): if action.case_type == old_case_type: action.case_type = case_type if should_edit("put_in_root"): module["put_in_root"] = json.loads(request.POST.get("put_in_root")) if should_edit("display_style"): module["display_style"] = request.POST.get("display_style") if should_edit("source_module_id"): module["source_module_id"] = request.POST.get("source_module_id") if should_edit("display_separately"): module["display_separately"] = json.loads( request.POST.get("display_separately")) if should_edit("parent_module"): parent_module = request.POST.get("parent_module") module.parent_select.module_id = parent_module if module_case_hierarchy_has_circular_reference(module): return HttpResponseBadRequest( _("The case hierarchy contains a circular reference.")) if should_edit("auto_select_case"): module["auto_select_case"] = request.POST.get( "auto_select_case") == 'true' if app.enable_module_filtering and should_edit('module_filter'): module['module_filter'] = request.POST.get('module_filter') if should_edit('case_list_form_id'): module.case_list_form.form_id = request.POST.get('case_list_form_id') if should_edit('case_list_form_label'): module.case_list_form.label[lang] = request.POST.get( 'case_list_form_label') if should_edit('case_list_post_form_workflow'): module.case_list_form.post_form_workflow = request.POST.get( 'case_list_post_form_workflow') if should_edit('case_list_form_media_image'): new_path = process_media_attribute( 'case_list_form_media_image', resp, request.POST.get('case_list_form_media_image')) module.case_list_form.set_icon(lang, new_path) if should_edit('case_list_form_media_audio'): new_path = process_media_attribute( 'case_list_form_media_audio', resp, request.POST.get('case_list_form_media_audio')) module.case_list_form.set_audio(lang, new_path) if should_edit('case_list-menu_item_media_image'): val = process_media_attribute( 'case_list-menu_item_media_image', resp, request.POST.get('case_list-menu_item_media_image')) module.case_list.set_icon(lang, val) if should_edit('case_list-menu_item_media_audio'): val = process_media_attribute( 'case_list-menu_item_media_audio', resp, request.POST.get('case_list-menu_item_media_audio')) module.case_list.set_audio(lang, val) if should_edit("name"): name = request.POST.get("name", None) module["name"][lang] = name resp['update'] = { '.variable-module_name': trans(module.name, [lang], use_delim=False) } if should_edit('comment'): module.comment = request.POST.get('comment') for SLUG in ('case_list', 'task_list'): show = '{SLUG}-show'.format(SLUG=SLUG) label = '{SLUG}-label'.format(SLUG=SLUG) if request.POST.get(show) == 'true' and (request.POST.get(label) == ''): # Show item, but empty label, was just getting ignored return HttpResponseBadRequest( "A label is required for {SLUG}".format(SLUG=SLUG)) if should_edit(SLUG): module[SLUG].show = json.loads(request.POST[show]) module[SLUG].label[lang] = request.POST[label] if should_edit("root_module_id"): old_root = module['root_module_id'] if not request.POST.get("root_module_id"): module["root_module_id"] = None else: module["root_module_id"] = request.POST.get("root_module_id") if not old_root and module['root_module_id']: track_workflow(request.couch_user.username, "User associated module with a parent") elif old_root and not module['root_module_id']: track_workflow(request.couch_user.username, "User orphaned a child module") if should_edit('excl_form_ids') and isinstance(module, ShadowModule): excl = request.POST.getlist('excl_form_ids') excl.remove( '0' ) # Placeholder value to make sure excl_form_ids is POSTed when no forms are excluded module.excluded_form_ids = excl handle_media_edits(request, module, should_edit, resp, lang) app.save(resp) resp['case_list-show'] = module.requires_case_details() return HttpResponse(json.dumps(resp))
def _edit_form_attr(request, domain, app_id, form_unique_id, attr): """ Called to edit any (supported) form attribute, given by attr """ ajax = json.loads(request.POST.get('ajax', 'true')) resp = {} app = get_app(domain, app_id) try: form = app.get_form(form_unique_id) except FormNotFoundException as e: if ajax: return HttpResponseBadRequest(six.text_type(e)) else: messages.error(request, _("There was an error saving, please try again!")) return back_to_main(request, domain, app_id=app_id) lang = request.COOKIES.get('lang', app.langs[0]) def should_edit(attribute): return attribute in request.POST if 'sha1' in request.POST and (should_edit("xform") or "xform" in request.FILES): conflict = _get_xform_conflict_response(form, request.POST['sha1']) if conflict is not None: return conflict if should_edit("name"): name = request.POST['name'] form.name[lang] = name if not form.form_type == "shadow_form": xform = form.wrapped_xform() if xform.exists(): xform.set_name(name) save_xform(app, form, xform.render()) resp['update'] = {'.variable-form_name': trans(form.name, [lang], use_delim=False)} if should_edit('comment'): form.comment = request.POST['comment'] if should_edit("name_enum"): name_enum = json.loads(request.POST.get("name_enum")) form.name_enum = [MappingItem(i) for i in name_enum] if should_edit("xform") or "xform" in request.FILES: try: # support FILES for upload and POST for ajax post from Vellum try: xform = request.FILES.get('xform').read() except Exception: xform = request.POST.get('xform') else: try: xform = six.text_type(xform, encoding="utf-8") except Exception: raise Exception("Error uploading form: Please make sure your form is encoded in UTF-8") if request.POST.get('cleanup', False): try: # First, we strip all newlines and reformat the DOM. px = parseString(xform.replace('\r\n', '')).toprettyxml() # Then we remove excess newlines from the DOM output. text_re = re.compile(r'>\n\s+([^<>\s].*?)\n\s+</', re.DOTALL) prettyXml = text_re.sub(r'>\g<1></', px) xform = prettyXml except Exception: pass if xform: if isinstance(xform, six.text_type): xform = xform.encode('utf-8') save_xform(app, form, xform) else: raise Exception("You didn't select a form to upload") except Exception as e: notify_exception(request, six.text_type(e)) if ajax: return HttpResponseBadRequest(six.text_type(e)) else: messages.error(request, six.text_type(e)) if should_edit("references") or should_edit("case_references"): form.case_references = _get_case_references(request.POST) if should_edit("show_count"): show_count = request.POST['show_count'] form.show_count = True if show_count == "True" else False if should_edit("put_in_root"): put_in_root = request.POST['put_in_root'] form.put_in_root = True if put_in_root == "True" else False if should_edit('form_filter'): form.form_filter = request.POST['form_filter'] if should_edit('post_form_workflow'): form.post_form_workflow = request.POST['post_form_workflow'] if should_edit('auto_gps_capture'): form.auto_gps_capture = request.POST['auto_gps_capture'] == 'true' if should_edit('is_release_notes_form'): form.is_release_notes_form = request.POST['is_release_notes_form'] == 'true' if should_edit('enable_release_notes'): form.enable_release_notes = request.POST['enable_release_notes'] == 'true' if not form.is_release_notes_form and form.enable_release_notes: return json_response( {'message': _("You can't enable a form as release notes without allowing it as " "a release notes form <TODO messaging>")}, status_code=400 ) if should_edit('no_vellum'): form.no_vellum = request.POST['no_vellum'] == 'true' if (should_edit("form_links_xpath_expressions") and should_edit("form_links_form_ids") and toggles.FORM_LINK_WORKFLOW.enabled(domain)): form_links = zip( request.POST.getlist('form_links_xpath_expressions'), request.POST.getlist('form_links_form_ids'), [ json.loads(datum_json) if datum_json else [] for datum_json in request.POST.getlist('datums_json') ], ) form.form_links = [FormLink( xpath=link[0], form_id=link[1], datums=[ FormDatum(name=datum['name'], xpath=datum['xpath']) for datum in link[2] ] ) for link in form_links] if should_edit('post_form_workflow_fallback'): form.post_form_workflow_fallback = request.POST.get('post_form_workflow_fallback') if should_edit('custom_instances'): instances = json.loads(request.POST.get('custom_instances')) try: # validate that custom instances can be added into the XML for instance in instances: etree.fromstring( "<instance id='{}' src='{}' />".format( instance.get('instanceId'), instance.get('instancePath') ) ) except etree.XMLSyntaxError as error: return json_response( {'message': _("There was an issue with your custom instances: {}").format(error.message)}, status_code=400 ) form.custom_instances = [ CustomInstance( instance_id=instance.get("instanceId"), instance_path=instance.get("instancePath"), ) for instance in instances ] if should_edit('custom_assertions'): assertions = json.loads(request.POST.get('custom_assertions')) try: # validate that custom assertions can be added into the XML for assertion in assertions: etree.fromstring( '<assertion test="{test}"><text><locale id="abc.def"/>{text}</text></assertion>'.format( **assertion ) ) except etree.XMLSyntaxError as error: return json_response( {'message': _("There was an issue with your custom assertions: {}").format(error.message)}, status_code=400 ) existing_assertions = {assertion.test: assertion for assertion in form.custom_assertions} new_assertions = [] for assertion in assertions: try: new_assertion = existing_assertions[assertion.get('test')] new_assertion.text[lang] = assertion.get('text') except KeyError: new_assertion = CustomAssertion( test=assertion.get('test'), text={lang: assertion.get('text')} ) new_assertions.append(new_assertion) form.custom_assertions = new_assertions if should_edit("shadow_parent"): form.shadow_parent_form_id = request.POST['shadow_parent'] if should_edit("custom_icon_form"): error_message = handle_custom_icon_edits(request, form, lang) if error_message: return json_response( {'message': error_message}, status_code=400 ) handle_media_edits(request, form, should_edit, resp, lang) app.save(resp) notify_form_changed(domain, request.couch_user, app_id, form_unique_id) if ajax: return HttpResponse(json.dumps(resp)) else: return back_to_main(request, domain, app_id=app_id, form_unique_id=form_unique_id)
def edit_module_attr(request, domain, app_id, module_unique_id, attr): """ Called to edit any (supported) module attribute, given by attr """ attributes = { "all": None, "auto_select_case": None, "case_list": ('case_list-show', 'case_list-label'), "case_list-menu_item_media_audio": None, "case_list-menu_item_media_image": None, 'case_list-menu_item_use_default_image_for_all': None, 'case_list-menu_item_use_default_audio_for_all': None, "case_list_form_id": None, "case_list_form_label": None, "case_list_form_media_audio": None, "case_list_form_media_image": None, 'case_list_form_use_default_image_for_all': None, 'case_list_form_use_default_audio_for_all': None, "case_list_post_form_workflow": None, "case_type": None, 'comment': None, "display_separately": None, "has_schedule": None, "media_audio": None, "media_image": None, "module_filter": None, "name": None, "name_enum": None, "parent_module": None, "put_in_root": None, "root_module_id": None, "source_module_id": None, "task_list": ('task_list-show', 'task_list-label'), "excl_form_ids": None, "display_style": None, "custom_icon_form": None, "custom_icon_text_body": None, "custom_icon_xpath": None, "use_default_image_for_all": None, "use_default_audio_for_all": None, } if attr not in attributes: return HttpResponseBadRequest() def should_edit(attribute): if attribute == attr: return True if 'all' == attr: if attributes[attribute]: for param in attributes[attribute]: if not request.POST.get(param): return False return True else: return request.POST.get(attribute) is not None app = get_app(domain, app_id) try: module = app.get_module_by_unique_id(module_unique_id) except ModuleNotFoundException: # temporary fallback module = app.get_module(module_unique_id) lang = request.COOKIES.get('lang', app.langs[0]) resp = {'update': {}, 'corrections': {}} if should_edit("custom_icon_form"): error_message = handle_custom_icon_edits(request, module, lang) if error_message: return json_response( {'message': error_message}, status_code=400 ) if should_edit("name_enum"): name_enum = json.loads(request.POST.get("name_enum")) module.name_enum = [MappingItem(i) for i in name_enum] if should_edit("case_type"): case_type = request.POST.get("case_type", None) if case_type == USERCASE_TYPE and not isinstance(module, AdvancedModule): return HttpResponseBadRequest('"{}" is a reserved case type'.format(USERCASE_TYPE)) elif case_type and not is_valid_case_type(case_type, module): return HttpResponseBadRequest("case type is improperly formatted") else: old_case_type = module["case_type"] module["case_type"] = case_type # rename other reference to the old case type all_advanced_modules = [] modules_with_old_case_type_exist = False for mod in app.modules: if isinstance(mod, AdvancedModule): all_advanced_modules.append(mod) modules_with_old_case_type_exist |= mod.case_type == old_case_type for mod in all_advanced_modules: for form in mod.forms: for action in form.actions.get_load_update_actions(): if action.case_type == old_case_type and action.details_module == module_unique_id: action.case_type = case_type if mod.unique_id == module_unique_id or not modules_with_old_case_type_exist: for action in form.actions.get_open_actions(): if action.case_type == old_case_type: action.case_type = case_type if should_edit("put_in_root"): module["put_in_root"] = json.loads(request.POST.get("put_in_root")) if should_edit("display_style"): module["display_style"] = request.POST.get("display_style") if should_edit("source_module_id"): module["source_module_id"] = request.POST.get("source_module_id") if should_edit("display_separately"): module["display_separately"] = json.loads(request.POST.get("display_separately")) if should_edit("parent_module"): parent_module = request.POST.get("parent_module") module.parent_select.module_id = parent_module if module_case_hierarchy_has_circular_reference(module): return HttpResponseBadRequest(_("The case hierarchy contains a circular reference.")) if should_edit("auto_select_case"): module["auto_select_case"] = request.POST.get("auto_select_case") == 'true' if app.enable_module_filtering and should_edit('module_filter'): module['module_filter'] = request.POST.get('module_filter') if should_edit('case_list_form_id'): module.case_list_form.form_id = request.POST.get('case_list_form_id') if should_edit('case_list_form_label'): module.case_list_form.label[lang] = request.POST.get('case_list_form_label') if should_edit('case_list_post_form_workflow'): module.case_list_form.post_form_workflow = request.POST.get('case_list_post_form_workflow') if should_edit("name"): name = request.POST.get("name", None) module["name"][lang] = name resp['update'] = {'.variable-module_name': trans(module.name, [lang], use_delim=False)} if should_edit('comment'): module.comment = request.POST.get('comment') for SLUG in ('case_list', 'task_list'): show = '{SLUG}-show'.format(SLUG=SLUG) label = '{SLUG}-label'.format(SLUG=SLUG) if request.POST.get(show) == 'true' and (request.POST.get(label) == ''): # Show item, but empty label, was just getting ignored return HttpResponseBadRequest("A label is required for {SLUG}".format(SLUG=SLUG)) if should_edit(SLUG): module[SLUG].show = json.loads(request.POST[show]) module[SLUG].label[lang] = request.POST[label] if should_edit("root_module_id"): old_root = module['root_module_id'] if not request.POST.get("root_module_id"): module["root_module_id"] = None else: module["root_module_id"] = request.POST.get("root_module_id") if not old_root and module['root_module_id']: track_workflow(request.couch_user.username, "User associated module with a parent") elif old_root and not module['root_module_id']: track_workflow(request.couch_user.username, "User orphaned a child module") if should_edit('excl_form_ids') and isinstance(module, ShadowModule): excl = request.POST.getlist('excl_form_ids') excl.remove('0') # Placeholder value to make sure excl_form_ids is POSTed when no forms are excluded module.excluded_form_ids = excl handle_media_edits(request, module, should_edit, resp, lang) handle_media_edits(request, module.case_list_form, should_edit, resp, lang, prefix='case_list_form_') handle_media_edits(request, module.case_list, should_edit, resp, lang, prefix='case_list-menu_item_') app.save(resp) resp['case_list-show'] = module.requires_case_details() return HttpResponse(json.dumps(resp))
def _edit_form_attr(request, domain, app_id, form_unique_id, attr): """ Called to edit any (supported) form attribute, given by attr """ ajax = json.loads(request.POST.get('ajax', 'true')) resp = {} app = get_app(domain, app_id) try: form = app.get_form(form_unique_id) except FormNotFoundException as e: if ajax: return HttpResponseBadRequest(unicode(e)) else: messages.error(request, _("There was an error saving, please try again!")) return back_to_main(request, domain, app_id=app_id) lang = request.COOKIES.get('lang', app.langs[0]) def should_edit(attribute): return attribute in request.POST if should_edit("name"): name = request.POST['name'] form.name[lang] = name if not form.form_type == "shadow_form": xform = form.wrapped_xform() if xform.exists(): xform.set_name(name) save_xform(app, form, xform.render()) resp['update'] = { '.variable-form_name': trans(form.name, [lang], use_delim=False) } if should_edit('comment'): form.comment = request.POST['comment'] if should_edit("xform") or "xform" in request.FILES: try: # support FILES for upload and POST for ajax post from Vellum try: xform = request.FILES.get('xform').read() except Exception: xform = request.POST.get('xform') else: try: xform = unicode(xform, encoding="utf-8") except Exception: raise Exception( "Error uploading form: Please make sure your form is encoded in UTF-8" ) if request.POST.get('cleanup', False): try: # First, we strip all newlines and reformat the DOM. px = parseString(xform.replace('\r\n', '')).toprettyxml() # Then we remove excess newlines from the DOM output. text_re = re.compile('>\n\s+([^<>\s].*?)\n\s+</', re.DOTALL) prettyXml = text_re.sub('>\g<1></', px) xform = prettyXml except Exception: pass if xform: save_xform(app, form, xform) else: raise Exception("You didn't select a form to upload") except Exception as e: if ajax: return HttpResponseBadRequest(unicode(e)) else: messages.error(request, unicode(e)) if should_edit("references") or should_edit("case_references"): form.case_references = _get_case_references(request.POST) if should_edit("show_count"): show_count = request.POST['show_count'] form.show_count = True if show_count == "True" else False if should_edit("put_in_root"): put_in_root = request.POST['put_in_root'] form.put_in_root = True if put_in_root == "True" else False if should_edit('form_filter'): form.form_filter = request.POST['form_filter'] if should_edit('post_form_workflow'): form.post_form_workflow = request.POST['post_form_workflow'] if should_edit('auto_gps_capture'): form.auto_gps_capture = request.POST['auto_gps_capture'] == 'true' if should_edit('no_vellum'): form.no_vellum = request.POST['no_vellum'] == 'true' if (should_edit("form_links_xpath_expressions") and should_edit("form_links_form_ids") and toggles.FORM_LINK_WORKFLOW.enabled(domain)): form_links = zip( request.POST.getlist('form_links_xpath_expressions'), request.POST.getlist('form_links_form_ids'), [ json.loads(datum_json) if datum_json else [] for datum_json in request.POST.getlist('datums_json') ], ) form.form_links = [ FormLink(xpath=link[0], form_id=link[1], datums=[ FormDatum(name=datum['name'], xpath=datum['xpath']) for datum in link[2] ]) for link in form_links ] if should_edit('post_form_workflow_fallback'): form.post_form_workflow_fallback = request.POST.get( 'post_form_workflow_fallback') if should_edit('custom_instances'): instances = json.loads(request.POST.get('custom_instances')) try: # validate that custom instances can be added into the XML for instance in instances: etree.fromstring("<instance id='{}' src='{}' />".format( instance.get('instanceId'), instance.get('instancePath'))) except etree.XMLSyntaxError as error: return json_response( { 'message': _("There was an issue with your custom instances: {}"). format(error.message) }, status_code=400) form.custom_instances = [ CustomInstance( instance_id=instance.get("instanceId"), instance_path=instance.get("instancePath"), ) for instance in instances ] if should_edit("shadow_parent"): form.shadow_parent_form_id = request.POST['shadow_parent'] if should_edit("custom_icon_form"): error_message = handle_custom_icon_edits(request, form, lang) if error_message: return json_response({'message': error_message}, status_code=400) handle_media_edits(request, form, should_edit, resp, lang) app.save(resp) notify_form_changed(domain, request.couch_user, app_id, form_unique_id) if ajax: return HttpResponse(json.dumps(resp)) else: return back_to_main(request, domain, app_id=app_id, form_unique_id=form_unique_id)