Exemplo n.º 1
0
def handle_custom_icon_edits(request, form_or_module, lang):
    if add_ons.show("custom_icon_badges", request, form_or_module.get_app()):
        icon_text_body = request.POST.get("custom_icon_text_body")
        icon_xpath = request.POST.get("custom_icon_xpath")
        icon_form = request.POST.get("custom_icon_form")

        # if there is a request to set custom icon
        if icon_form:
            # validate that only of either text or xpath should be present
            if (icon_text_body and icon_xpath) or (not icon_text_body
                                                   and not icon_xpath):
                return _(
                    "Please enter either text body or xpath for custom icon")

            # a form should have just one custom icon for now
            # so this just adds a new one with params or replaces the existing one with new params
            form_custom_icon = (form_or_module.custom_icon if
                                form_or_module.custom_icon else CustomIcon())
            form_custom_icon.form = icon_form
            form_custom_icon.text[lang] = icon_text_body
            form_custom_icon.xpath = icon_xpath

            form_or_module.custom_icons = [form_custom_icon]

        # if there is a request to unset custom icon
        if not icon_form and form_or_module.custom_icon:
            form_or_module.custom_icons = []
Exemplo n.º 2
0
def _get_vellum_features(request, domain, app):
    """
    Returns the context of features passed into vellum when it is initialized.
    """
    vellum_features = toggles.toggles_dict(username=request.user.username,
                                           domain=domain)
    vellum_features.update({
        'group_in_field_list':
        app.enable_group_in_field_list,
        'image_resize':
        app.enable_image_resize,
        'markdown_in_groups':
        app.enable_markdown_in_groups,
        'lookup_tables':
        domain_has_privilege(domain, privileges.LOOKUP_TABLES),
        'templated_intents':
        domain_has_privilege(domain, privileges.TEMPLATED_INTENTS),
        'custom_intents':
        domain_has_privilege(domain, privileges.CUSTOM_INTENTS),
        'rich_text':
        True,
        'sorted_itemsets':
        app.enable_sorted_itemsets,
        'advanced_itemsets':
        add_ons.show("advanced_itemsets", request, app),
        'markdown_tables':
        app.enable_markdown_tables,
    })
    return vellum_features
Exemplo n.º 3
0
def new_module(request, domain, app_id):
    "Adds a module to an app"
    app = get_app(domain, app_id)
    from corehq.apps.app_manager.views.utils import get_default_followup_form_xml
    lang = request.COOKIES.get('lang', app.langs[0])
    name = request.POST.get('name')
    module_type = request.POST.get('module_type', 'case')

    if module_type == 'case' or module_type == 'survey':  # survey option added for V2
        if module_type == 'case':
            name = name or 'Case List'
        else:
            name = name or 'Surveys'

        module = app.add_module(Module.new_module(name, lang))
        module_id = module.id

        form_id = None
        unstructured = add_ons.show("empty_case_lists", request, app)
        if module_type == 'case':
            if not unstructured:
                form_id = 0

                # registration form
                register = app.new_form(module_id, _("Registration Form"), lang)
                register.actions.open_case = OpenCaseAction(condition=FormActionCondition(type='always'))
                register.actions.update_case = UpdateCaseAction(
                    condition=FormActionCondition(type='always'))

                # one followup form
                msg = _("This is your follow up form. "
                        "Delete this label and add questions for any follow up visits.")
                attachment = get_default_followup_form_xml(context={'lang': lang, 'default_label': msg})
                followup = app.new_form(module_id, _("Followup Form"), lang, attachment=attachment)
                followup.requires = "case"
                followup.actions.update_case = UpdateCaseAction(condition=FormActionCondition(type='always'))

            _init_module_case_type(module)
        else:
            form_id = 0
            app.new_form(module_id, _("Survey"), lang)

        app.save()
        response = back_to_main(request, domain, app_id=app_id,
                                module_id=module_id, form_id=form_id)
        response.set_cookie('suppress_build_errors', 'yes')
        return response
    elif module_type in MODULE_TYPE_MAP:
        fn = MODULE_TYPE_MAP[module_type][FN]
        validations = MODULE_TYPE_MAP[module_type][VALIDATIONS]
        error = next((v[1] for v in validations if v[0](app)), None)
        if error:
            messages.warning(request, error)
            return back_to_main(request, domain, app_id=app.id)
        else:
            return fn(request, domain, app, name, lang)
    else:
        logger.error('Unexpected module type for new module: "%s"' % module_type)
        return back_to_main(request, domain, app_id=app_id)
Exemplo n.º 4
0
def new_module(request, domain, app_id):
    "Adds a module to an app"
    app = get_app(domain, app_id)
    from corehq.apps.app_manager.views.utils import get_default_followup_form_xml
    lang = request.COOKIES.get('lang', app.langs[0])
    name = request.POST.get('name')
    module_type = request.POST.get('module_type', 'case')

    if module_type == 'case' or module_type == 'survey':  # survey option added for V2
        if module_type == 'case':
            name = name or 'Case List'
        else:
            name = name or 'Surveys'

        module = app.add_module(Module.new_module(name, lang))
        module_id = module.id

        form_id = None
        unstructured = add_ons.show("empty_case_lists", request, app)
        if module_type == 'case':
            if not unstructured:
                form_id = 0

                # registration form
                register = app.new_form(module_id, _("Registration Form"), lang)
                register.actions.open_case = OpenCaseAction(condition=FormActionCondition(type='always'))
                register.actions.update_case = UpdateCaseAction(
                    condition=FormActionCondition(type='always'))

                # one followup form
                msg = _("This is your follow up form. "
                        "Delete this label and add questions for any follow up visits.")
                attachment = get_default_followup_form_xml(context={'lang': lang, 'default_label': msg})
                followup = app.new_form(module_id, _("Followup Form"), lang, attachment=attachment)
                followup.requires = "case"
                followup.actions.update_case = UpdateCaseAction(condition=FormActionCondition(type='always'))

            _init_module_case_type(module)
        else:
            form_id = 0
            app.new_form(module_id, _("Survey"), lang)

        app.save()
        response = back_to_main(request, domain, app_id=app_id,
                                module_id=module_id, form_id=form_id)
        response.set_cookie('suppress_build_errors', 'yes')
        return response
    elif module_type in MODULE_TYPE_MAP:
        fn = MODULE_TYPE_MAP[module_type][FN]
        validations = MODULE_TYPE_MAP[module_type][VALIDATIONS]
        error = next((v[1] for v in validations if v[0](app)), None)
        if error:
            messages.warning(request, error)
            return back_to_main(request, domain, app_id=app.id)
        else:
            return fn(request, domain, app, name, lang)
    else:
        logger.error('Unexpected module type for new module: "%s"' % module_type)
        return back_to_main(request, domain, app_id=app_id)
Exemplo n.º 5
0
def _get_vellum_features(request, domain, app):
    """
    Returns the context of features passed into vellum when it is initialized.
    """
    vellum_features = toggles.toggles_dict(username=request.user.username,
                                           domain=domain)
    vellum_features.update({
        'group_in_field_list': app.enable_group_in_field_list,
        'image_resize': app.enable_image_resize,
        'markdown_in_groups': app.enable_markdown_in_groups,
        'lookup_tables': domain_has_privilege(domain, privileges.LOOKUP_TABLES),
        'templated_intents': domain_has_privilege(domain,
                                                  privileges.TEMPLATED_INTENTS),
        'custom_intents': domain_has_privilege(domain,
                                               privileges.CUSTOM_INTENTS),
        'rich_text': True,
        'sorted_itemsets': app.enable_sorted_itemsets,
        'advanced_itemsets': add_ons.show("advanced_itemsets", request, app),
        'remote_requests': (app.enable_remote_requests
                            and toggles.REMOTE_REQUEST_QUESTION_TYPE.enabled(domain)),
    })
    return vellum_features
Exemplo n.º 6
0
def view_generic(request,
                 domain,
                 app_id=None,
                 module_id=None,
                 form_id=None,
                 copy_app_form=None,
                 release_manager=False,
                 module_unique_id=None,
                 form_unique_id=None):
    """
    This is the main view for the app. All other views redirect to here.

    """
    if form_id and not module_id and module_unique_id is None:
        return bail(request, domain, app_id)

    app = module = form = None
    try:
        if app_id:
            app = get_app(domain, app_id)

        if module_id:
            try:
                module = app.get_module(module_id)
            except ModuleNotFoundException:
                raise Http404()
            if not module.unique_id:
                module.get_or_create_unique_id()
                app.save()
        elif module_unique_id:
            try:
                module = app.get_module_by_unique_id(module_unique_id)
            except ModuleNotFoundException:
                raise Http404()
            module_id = module.id

        if form_id and module is not None:
            try:
                form = module.get_form(form_id)
            except IndexError:
                raise Http404()
        elif form_unique_id:
            try:
                form = app.get_form(form_unique_id)
            except FormNotFoundException:
                raise Http404()
            form_id = form.id

        if form is not None and module is None:
            # this is the case where only the form_unique_id is given
            module = form.get_module()
            module_id = module.id

    except (ModuleNotFoundException, FormNotFoundException):
        return bail(request, domain, app_id)

    # Application states that should no longer exist
    if app:
        if app.application_version == APP_V1:
            _assert = soft_assert()
            _assert(False, 'App version 1.0', {
                'domain': domain,
                'app_id': app_id
            })
            return render(request, "app_manager/no_longer_supported.html", {
                'domain': domain,
                'app': app,
            })
        if not app.vellum_case_management and not app.is_remote_app():
            # Soft assert but then continue rendering; template will contain a user-facing warning
            _assert = soft_assert(['jschweers' + '@' + 'dimagi.com'])
            _assert(False, 'vellum_case_management=False', {
                'domain': domain,
                'app_id': app_id
            })
        if (form is not None
                and "usercase_preload" in getattr(form, "actions", {})
                and form.actions.usercase_preload.preload):
            _assert = soft_assert(['dmiller' + '@' + 'dimagi.com'])
            _assert(
                False, 'User property easy refs + old-style config = bad', {
                    'domain': domain,
                    'app_id': app_id,
                    'module_id': module_id,
                    'module_unique_id': module_unique_id,
                    'form_id': form_id,
                    'form_unique_id': form_unique_id,
                })

    context = get_apps_base_context(request, domain, app)
    if app and app.copy_of:
        # don't fail hard.
        return HttpResponseRedirect(
            reverse(
                "view_app",
                args=[domain, app.copy_of]  # TODO - is this right?
            ))

    # grandfather in people who set commcare sense earlier
    if app and 'use_commcare_sense' in app:
        if app['use_commcare_sense']:
            if 'features' not in app.profile:
                app.profile['features'] = {}
            app.profile['features']['sense'] = 'true'
        del app['use_commcare_sense']
        app.save()

    context.update({
        'module': module,
        'form': form,
    })

    lang = context['lang']
    if app and not module and hasattr(app, 'translations'):
        context.update({"translations": app.translations.get(lang, {})})

    if app and not app.is_remote_app():
        context.update({
            'add_ons': add_ons.get_dict(request, app, module, form),
            'add_ons_layout': add_ons.get_layout(request),
        })

    if form:
        template, form_context = get_form_view_context_and_template(
            request, domain, form, context['langs'])
        context.update(form_context)
    elif module:
        template = get_module_template(request.user, module)
        # make sure all modules have unique ids
        app.ensure_module_unique_ids(should_save=True)
        module_context = get_module_view_context(app, module, lang)
        context.update(module_context)
    elif app:
        context.update(get_app_view_context(request, app))

        template = 'app_manager/app_view_settings.html'
        if release_manager:
            template = 'app_manager/app_view_release_manager.html'
        if release_manager:
            context.update(get_releases_context(request, domain, app_id))
        context.update({
            'is_app_settings_page': not release_manager,
        })
    else:
        from corehq.apps.dashboard.views import DomainDashboardView
        return HttpResponseRedirect(
            reverse(DomainDashboardView.urlname, args=[domain]))

    # update multimedia context for forms and modules.
    menu_host = form or module
    if menu_host:
        default_file_name = 'module%s' % module_id
        if form:
            default_file_name = '%s_form%s' % (default_file_name, form_id)

        specific_media = [{
            'menu_refs':
            app.get_menu_media(module,
                               module_id,
                               form=form,
                               form_index=form_id,
                               to_language=lang),
            'default_file_name':
            '{name}_{lang}'.format(name=default_file_name, lang=lang),
        }]

        if not form and module and not isinstance(
                module, ReportModule) and module.uses_media():

            def _make_name(suffix):
                return "{default_name}_{suffix}_{lang}".format(
                    default_name=default_file_name,
                    suffix=suffix,
                    lang=lang,
                )

            specific_media.append({
                'menu_refs':
                app.get_case_list_form_media(module,
                                             module_id,
                                             to_language=lang),
                'default_file_name':
                _make_name('case_list_form'),
                'qualifier':
                'case_list_form_',
            })
            specific_media.append({
                'menu_refs':
                app.get_case_list_menu_item_media(module,
                                                  module_id,
                                                  to_language=lang),
                'default_file_name':
                _make_name('case_list_menu_item'),
                'qualifier':
                'case_list-menu_item_',
            })
            if (toggles.CASE_LIST_LOOKUP.enabled(request.user.username)
                    or toggles.CASE_LIST_LOOKUP.enabled(app.domain)):
                specific_media.append({
                    'menu_refs':
                    app.get_case_list_lookup_image(module, module_id),
                    'default_file_name':
                    '{}_case_list_lookup'.format(default_file_name),
                    'qualifier':
                    'case-list-lookupcase',
                })

                if hasattr(module, 'product_details'):
                    specific_media.append({
                        'menu_refs':
                        app.get_case_list_lookup_image(module,
                                                       module_id,
                                                       type='product'),
                        'default_file_name':
                        '{}_product_list_lookup'.format(default_file_name),
                        'qualifier':
                        'case-list-lookupproduct',
                    })

        uploaders = {
            'icon':
            MultimediaImageUploadController(
                "hqimage",
                reverse(ProcessImageFileUploadView.name,
                        args=[app.domain, app.get_id])),
            'audio':
            MultimediaAudioUploadController(
                "hqaudio",
                reverse(ProcessAudioFileUploadView.name,
                        args=[app.domain, app.get_id])),
        }
        context.update({
            'multimedia': {
                "object_map": app.get_object_map(),
                'upload_managers': uploaders,
                'upload_managers_js':
                {type: u.js_options
                 for type, u in uploaders.iteritems()},
            }
        })
        context['module_icon'] = None
        if add_ons.show("custom_icon_badges", request, module.get_app()):
            context[
                'module_icon'] = module.custom_icon if module.custom_icon else CustomIcon(
                )
        try:
            context['multimedia']['references'] = app.get_references()
        except ReportConfigurationNotFoundError:
            pass
        context['nav_menu_media_specifics'] = specific_media

    error = request.GET.get('error', '')

    context.update({
        'error': error,
        'app': app,
    })

    # Pass form for Copy Application to template
    domain_names = [d.name for d in Domain.active_for_user(request.couch_user)]
    domain_names.sort()
    if app and copy_app_form is None:
        toggle_enabled = toggles.EXPORT_ZIPPED_APPS.enabled(
            request.user.username)
        copy_app_form = CopyApplicationForm(
            domain, app, export_zipped_apps_enabled=toggle_enabled)
        context.update({
            'domain_names': domain_names,
        })
    linked_apps_enabled = toggles.LINKED_APPS.enabled(domain)
    context.update({
        'copy_app_form': copy_app_form,
        'linked_apps_enabled': linked_apps_enabled,
    })

    context['latest_commcare_version'] = get_commcare_versions(
        request.user)[-1]
    context['current_app_version_url'] = reverse('current_app_version',
                                                 args=[domain, app_id])

    if app and app.doc_type == 'Application' and has_privilege(
            request, privileges.COMMCARE_LOGO_UPLOADER):
        uploader_slugs = ANDROID_LOGO_PROPERTY_MAPPING.keys()
        from corehq.apps.hqmedia.controller import MultimediaLogoUploadController
        from corehq.apps.hqmedia.views import ProcessLogoFileUploadView
        uploaders = [
            MultimediaLogoUploadController(
                slug,
                reverse(
                    ProcessLogoFileUploadView.name,
                    args=[domain, app_id, slug],
                )) for slug in uploader_slugs
        ]
        context.update({
            "sessionid": request.COOKIES.get('sessionid'),
            "uploaders": uploaders,
            "uploaders_js": [u.js_options for u in uploaders],
            "refs": {
                slug: ApplicationMediaReference(
                    app.logo_refs.get(slug, {}).get("path", slug),
                    media_class=CommCareImage,
                    module_id=app.logo_refs.get(slug, {}).get("m_id"),
                ).as_dict()
                for slug in uploader_slugs
            },
            "media_info": {
                slug: app.logo_refs.get(slug)
                for slug in uploader_slugs if app.logo_refs.get(slug)
            },
        })

    context.update({
        'show_live_preview':
        app
        and should_show_preview_app(request, app, request.couch_user.username),
        'can_preview_form':
        request.couch_user.has_permission(domain, 'edit_data')
    })

    confirm = request.session.pop('CONFIRM', False)
    context.update({'confirm': confirm})

    response = render(request, template, context)

    response.set_cookie('lang', encode_if_unicode(lang))
    return response
Exemplo n.º 7
0
def get_form_view_context_and_template(request,
                                       domain,
                                       form,
                                       langs,
                                       messages=messages):
    xform_questions = []
    xform = None
    form_errors = []
    xform_validation_errored = False
    xform_validation_missing = False

    try:
        xform = form.wrapped_xform()
    except XFormException as e:
        form_errors.append(u"Error in form: %s" % e)
    except Exception as e:
        logging.exception(e)
        form_errors.append(u"Unexpected error in form: %s" % e)

    if xform and xform.exists():
        if xform.already_has_meta():
            messages.warning(
                request, "This form has a meta block already! "
                "It may be replaced by CommCare HQ's standard meta block.")

        try:
            xform_questions = xform.get_questions(langs, include_triggers=True)
            form.validate_form()
        except etree.XMLSyntaxError as e:
            form_errors.append(u"Syntax Error: %s" % e)
        except AppEditingError as e:
            form_errors.append(u"Error in application: %s" % e)
        except XFormValidationError:
            xform_validation_errored = True
            # showing these messages is handled by validate_form_for_build ajax
            pass
        except XFormValidationFailed:
            xform_validation_missing = True
            messages.warning(request,
                             _("Unable to validate form due to server error."))
        except XFormException as e:
            form_errors.append(u"Error in form: %s" % e)
        # any other kind of error should fail hard,
        # but for now there are too many for that to be practical
        except Exception as e:
            if settings.DEBUG:
                raise
            notify_exception(request, 'Unexpected Build Error')
            form_errors.append(u"Unexpected System Error: %s" % e)
        else:
            # remove upload questions (attachments) until MM Case Properties
            # are released to general public
            is_previewer = toggles.MM_CASE_PROPERTIES.enabled_for_request(
                request)
            xform_questions = [
                q for q in xform_questions
                if q["tag"] != "upload" or is_previewer
            ]

        if not form_errors and not xform_validation_missing and not xform_validation_errored:
            try:
                form_action_errors = form.validate_for_build()
                if not form_action_errors:
                    form.add_stuff_to_xform(xform)
            except CaseError as e:
                messages.error(request, u"Error in Case Management: %s" % e)
            except XFormException as e:
                messages.error(request, unicode(e))
            except Exception as e:
                if settings.DEBUG:
                    raise
                logging.exception(unicode(e))
                messages.error(request, u"Unexpected Error: %s" % e)

    try:
        languages = xform.get_languages()
    except Exception:
        languages = []

    for err in form_errors:
        messages.error(request, err)

    module_case_types = []
    app = form.get_app()
    all_modules = list(app.get_modules())
    for module in all_modules:
        for case_type in module.get_case_types():
            module_case_types.append({
                'id': module.unique_id,
                'module_name': trans(module.name, langs),
                'case_type': case_type,
                'module_type': module.doc_type
            })
    module = form.get_module()

    if not form.unique_id:
        form.get_unique_id()
        app.save()

    allow_usercase = domain_has_privilege(request.domain, privileges.USER_CASE)
    valid_index_names = DEFAULT_CASE_INDEX_IDENTIFIERS.values()
    if allow_usercase:
        valid_index_names.append(USERCASE_PREFIX[0:-1])  # strip trailing slash

    form_has_schedule = isinstance(form, AdvancedForm) and module.has_schedule
    case_config_options = {
        'caseType': form.get_case_type(),
        'moduleCaseTypes': module_case_types,
        'propertiesMap': get_all_case_properties(app),
        'propertyDescriptions': get_case_property_description_dict(domain),
        'questions': xform_questions,
        'reserved_words': load_case_reserved_words(),
        'usercasePropertiesMap': get_usercase_properties(app),
    }
    context = {
        'nav_form':
        form,
        'xform_languages':
        languages,
        'form_errors':
        form_errors,
        'xform_validation_errored':
        xform_validation_errored,
        'xform_validation_missing':
        xform_validation_missing,
        'allow_form_copy':
        isinstance(form, (Form, AdvancedForm)),
        'allow_form_filtering':
        not form_has_schedule,
        'allow_form_workflow':
        True,
        'uses_form_workflow':
        form.post_form_workflow == WORKFLOW_FORM,
        'allow_usercase':
        allow_usercase,
        'is_usercase_in_use':
        is_usercase_in_use(request.domain),
        'is_module_filter_enabled':
        app.enable_module_filtering,
        'root_requires_same_case':
        module.root_requires_same_case(),
        'is_case_list_form':
        form.is_case_list_form,
        'edit_name_url':
        reverse('edit_form_attr',
                args=[app.domain, app.id, form.unique_id, 'name']),
        'form_filter_patterns': {
            'case': CASE_XPATH_PATTERN_MATCHES,
            'case_substring': CASE_XPATH_SUBSTRING_MATCHES,
            'usercase': USER_CASE_XPATH_PATTERN_MATCHES,
            'usercase_substring': USER_CASE_XPATH_SUBSTRING_MATCHES,
        },
        'custom_instances': [{
            'instanceId': instance.instance_id,
            'instancePath': instance.instance_path
        } for instance in form.custom_instances],
        'can_preview_form':
        request.couch_user.has_permission(domain, 'edit_data'),
        'form_icon':
        None,
    }

    if add_ons.show("custom_icon_badges", request, form.get_app()):
        context[
            'form_icon'] = form.custom_icon if form.custom_icon else CustomIcon(
            )

    if context['allow_form_workflow'] and toggles.FORM_LINK_WORKFLOW.enabled(
            domain):

        def qualified_form_name(form, auto_link):
            module_name = trans(module.name, langs)
            form_name = trans(form.name, langs)
            star = '* ' if auto_link else '  '
            return u"{}{} -> {}".format(star, module_name, form_name)

        modules = filter(lambda m: m.case_type == module.case_type,
                         all_modules)
        if getattr(module, 'root_module_id',
                   None) and module.root_module not in modules:
            modules.append(module.root_module)
        auto_linkable_forms = list(
            itertools.chain.from_iterable(
                list(m.get_forms()) for m in modules))

        def linkable_form(candidate_form):
            auto_link = candidate_form in auto_linkable_forms
            return {
                'unique_id': candidate_form.unique_id,
                'name': qualified_form_name(candidate_form, auto_link),
                'auto_link': auto_link
            }

        context['linkable_forms'] = [
            linkable_form(candidate_form) for candidate_module in all_modules
            for candidate_form in candidate_module.get_forms()
        ]

    if isinstance(form, AdvancedForm):

        def commtrack_programs():
            if app.commtrack_enabled:
                programs = Program.by_domain(app.domain)
                return [{
                    'value': program.get_id,
                    'label': program.name
                } for program in programs]
            else:
                return []

        all_programs = [{'value': '', 'label': _('All Programs')}]
        case_config_options.update({
            'commtrack_enabled':
            app.commtrack_enabled,
            'commtrack_programs':
            all_programs + commtrack_programs(),
            'module_id':
            module.unique_id,
            'save_url':
            reverse("edit_advanced_form_actions",
                    args=[app.domain, app.id, form.unique_id]),
        })
        if form.form_type == "shadow_form":
            case_config_options.update({
                'actions': form.extra_actions,
                'isShadowForm': True,
            })
        else:
            case_config_options.update({
                'actions': form.actions,
                'isShadowForm': False,
            })
        if getattr(module, 'has_schedule', False):
            schedule_options = get_schedule_context(form)
            schedule_options.update({
                'phase':
                schedule_options['schedule_phase'],
                'questions':
                xform_questions,
                'save_url':
                reverse("edit_visit_schedule",
                        args=[app.domain, app.id, form.unique_id]),
                'schedule':
                form.schedule,
            })
            context.update({
                'schedule_options': schedule_options,
            })
    else:
        context.update({
            'show_custom_ref':
            toggles.APP_BUILDER_CUSTOM_PARENT_REF.enabled_for_request(request),
        })
        case_config_options.update({
            'actions':
            form.actions,
            'allowUsercase':
            allow_usercase,
            'save_url':
            reverse("edit_form_actions",
                    args=[app.domain, app.id, form.unique_id]),
            'valid_index_names':
            valid_index_names,
        })

    context.update({'case_config_options': case_config_options})
    return "app_manager/form_view.html", context