Exemplo n.º 1
0
def get_module_template(domain, module):
    if isinstance(module, CareplanModule):
        return get_app_manager_template(
            domain,
            "app_manager/v1/module_view_careplan.html",
            "app_manager/v2/module_view_careplan.html",
        )
    elif isinstance(module, AdvancedModule):
        return get_app_manager_template(
            domain,
            "app_manager/v1/module_view_advanced.html",
            "app_manager/v2/module_view_advanced.html",
        )
    elif isinstance(module, ReportModule):
        return get_app_manager_template(
            domain,
            'app_manager/v1/module_view_report.html',
            'app_manager/v2/module_view_report.html',
        )
    else:
        return get_app_manager_template(
            domain,
            "app_manager/v1/module_view.html",
            "app_manager/v2/module_view.html",
        )
Exemplo n.º 2
0
def _load_custom_commcare_settings(user=None):
    path = os.path.join(os.path.dirname(__file__), 'static', 'app_manager',
                        'json')
    settings = []
    with open(
            os.path.join(
                path,
                get_app_manager_template(
                    user, 'v1/commcare-profile-settings.yaml',
                    'v2/commcare-profile-settings.yaml'))) as f:
        for setting in yaml.load(f):
            if not setting.get('type'):
                setting['type'] = 'properties'
            settings.append(setting)

    with open(
            os.path.join(
                path,
                get_app_manager_template(
                    user, 'v1/commcare-app-settings.yaml',
                    'v2/commcare-app-settings.yaml'))) as f:
        for setting in yaml.load(f):
            if not setting.get('type'):
                setting['type'] = 'hq'
            settings.append(setting)
    for setting in settings:
        if not setting.get('widget'):
            setting['widget'] = 'select'

        for prop in PROFILE_SETTINGS_TO_TRANSLATE:
            if prop in setting:
                setting[prop] = _translate_setting(setting, prop)
    return settings
Exemplo n.º 3
0
def _load_custom_commcare_settings(domain=None):
    path = os.path.join(os.path.dirname(__file__), 'static', 'app_manager', 'json')
    settings = []
    with open(os.path.join(
            path,
            get_app_manager_template(
                domain,
                'v1/commcare-profile-settings.yaml',
                'v2/commcare-profile-settings.yaml'
            )
    )) as f:
        for setting in yaml.load(f):
            if not setting.get('type'):
                setting['type'] = 'properties'
            settings.append(setting)

    with open(os.path.join(path, get_app_manager_template(
        domain,
        'v1/commcare-app-settings.yaml',
        'v2/commcare-app-settings.yaml'
    ))) as f:
        for setting in yaml.load(f):
            if not setting.get('type'):
                setting['type'] = 'hq'
            settings.append(setting)
    for setting in settings:
        if not setting.get('widget'):
            setting['widget'] = 'select'
        # i18n; not statically analyzable
        setting['name'] = ugettext_noop(setting['name'])
    return settings
Exemplo n.º 4
0
def _load_custom_commcare_settings(user=None):
    path = os.path.join(os.path.dirname(__file__), 'static', 'app_manager',
                        'json')
    settings = []
    with open(
            os.path.join(
                path,
                get_app_manager_template(
                    user, 'v1/commcare-profile-settings.yaml',
                    'v2/commcare-profile-settings.yaml'))) as f:
        for setting in yaml.load(f):
            if not setting.get('type'):
                setting['type'] = 'properties'
            settings.append(setting)

    with open(
            os.path.join(
                path,
                get_app_manager_template(
                    user, 'v1/commcare-app-settings.yaml',
                    'v2/commcare-app-settings.yaml'))) as f:
        for setting in yaml.load(f):
            if not setting.get('type'):
                setting['type'] = 'hq'
            settings.append(setting)
    for setting in settings:
        if not setting.get('widget'):
            setting['widget'] = 'select'
        # i18n; not statically analyzable
        setting['name'] = ugettext_noop(setting['name'])
    return settings
Exemplo n.º 5
0
def download_index(request, domain, app_id):
    """
    A landing page, mostly for debugging, that has links the jad and jar as well as
    all the resource files that will end up zipped into the jar.

    """
    template = get_app_manager_template(
        domain,
        "app_manager/v1/download_index.html",
        "app_manager/v2/download_index.html",
    )

    files = []
    try:
        files = source_files(request.app)
    except Exception:
        messages.error(request,
                       _("We were unable to get your files "
                         "because your Application has errors. "
                         "Please click <strong>Make New Version</strong> "
                         "under <strong>Deploy</strong> "
                         "for feedback on how to fix these errors."),
                       extra_tags='html')
    return render(
        request, template, {
            'app': request.app,
            'files': [{
                'name': f[0],
                'source': f[1]
            } for f in files],
            'supports_j2me': request.app.build_spec.supports_j2me(),
        })
Exemplo n.º 6
0
 def dispatch(self, request, *args, **kwargs):
     self.template_name = get_app_manager_template(
         request.user,
         self.template_name,
         'app_manager/v2/app_diff.html',
     )
     return super(AppDiffView, self).dispatch(request, *args, **kwargs)
Exemplo n.º 7
0
def odk_install(request, domain, app_id, with_media=False):
    app = get_app(domain, app_id)
    qr_code_view = "odk_qr_code" if not with_media else "odk_media_qr_code"
    build_profile_id = request.GET.get('profile')
    profile_url = app.odk_profile_display_url if not with_media else app.odk_media_profile_display_url
    if build_profile_id is not None:
        profile_url += '?profile={profile}'.format(profile=build_profile_id)
    context = {
        "domain":
        domain,
        "app":
        app,
        "qr_code":
        reverse(qr_code_view,
                args=[domain, app_id],
                params={'profile': build_profile_id}),
        "profile_url":
        profile_url,
    }
    template = get_app_manager_template(
        request.user,
        "app_manager/v1/odk_install.html",
        "app_manager/v2/odk_install.html",
    )
    return render(request, template, context)
Exemplo n.º 8
0
def save_copy(request, domain, app_id):
    """
    Saves a copy of the app to a new doc.
    See VersionedDoc.save_copy

    """
    track_built_app_on_hubspot.delay(request.couch_user)
    comment = request.POST.get('comment')
    app = get_app(domain, app_id)
    try:
        errors = app.validate_app()
    except ModuleIdMissingException:
        # For apps (mainly Exchange apps) that lost unique_id attributes on Module
        app.ensure_module_unique_ids(should_save=True)
        errors = app.validate_app()

    if not errors:
        try:
            copy = app.make_build(
                comment=comment,
                user_id=request.couch_user.get_id,
                previous_version=app.get_latest_app(released_only=False))
            copy.save(increment_version=False)
        finally:
            # To make a RemoteApp always available for building
            if app.is_remote_app():
                app.save(increment_version=True)

        _track_build_for_app_preview(domain, request.couch_user, app_id,
                                     'User created a build')

    else:
        copy = None
    copy = copy and SavedAppBuild.wrap(copy.to_json()).to_saved_build_json(
        get_timezone_for_user(request.couch_user, domain))
    lang, langs = get_langs(request, app)
    if copy:
        # Set if build is supported for Java Phones
        j2me_enabled_configs = CommCareBuildConfig.j2me_enabled_config_labels()
        copy['j2me_enabled'] = copy['menu_item_label'] in j2me_enabled_configs

    template = get_app_manager_template(
        request.user,
        "app_manager/v1/partials/build_errors.html",
        "app_manager/v2/partials/build_errors.html",
    )
    return json_response({
        "saved_app":
        copy,
        "error_html":
        render_to_string(
            template, {
                'request': request,
                'app': get_app(domain, app_id),
                'build_errors': errors,
                'domain': domain,
                'langs': langs,
                'lang': lang
            }),
    })
Exemplo n.º 9
0
def validate_module_for_build(request, domain, app_id, module_id, ajax=True):
    app = get_app(domain, app_id)
    try:
        module = app.get_module(module_id)
    except ModuleNotFoundException:
        raise Http404()
    errors = module.validate_for_build()
    lang, langs = get_langs(request, app)

    response_html = render_to_string(
        get_app_manager_template(
            domain,
            'app_manager/v1/partials/build_errors.html',
            'app_manager/v2/partials/build_errors.html',
        ), {
            'request': request,
            'app': app,
            'build_errors': errors,
            'not_actual_build': True,
            'domain': domain,
            'langs': langs,
            'lang': lang
        })
    if ajax:
        return json_response({'error_html': response_html})
    return HttpResponse(response_html)
Exemplo n.º 10
0
def multimedia_ajax(request, domain, app_id):

    template = get_app_manager_template(
        domain,
        'app_manager/v1/partials/multimedia_ajax.html',
        'app_manager/v2/partials/multimedia_ajax.html',
    )

    app = get_app(domain, app_id)
    if app.get_doc_type() == 'Application':
        try:
            multimedia_state = app.check_media_state()
        except ProcessTimedOut:
            notify_exception(request)
            messages.warning(
                request, ("We were unable to check if your forms had errors. "
                          "Refresh the page and we will try again."))
            multimedia_state = {
                'has_media': False,
                'has_form_errors': True,
                'has_missing_refs': False,
            }
        context = {
            'multimedia_state': multimedia_state,
            'domain': domain,
            'app': app,
        }
        return render(request, template, context)
    else:
        raise Http404()
Exemplo n.º 11
0
 def dispatch(self, request, *args, **kwargs):
     self.template_name = get_app_manager_template(
         self.domain,
         self.template_name,
         'app_manager/v2/summary.html',
     )
     return super(AppSummaryView, self).dispatch(request, *args, **kwargs)
Exemplo n.º 12
0
def _load_commcare_settings_layout(doc_type, user):
    settings = dict([('{0}.{1}'.format(setting.get('type'),
                                       setting.get('id')), setting)
                     for setting in _load_custom_commcare_settings(user)])
    path = os.path.join(os.path.dirname(__file__), 'static', 'app_manager',
                        'json')
    with open(
            os.path.join(
                path,
                get_app_manager_template(
                    user, 'v1/commcare-settings-layout.yaml',
                    'v2/commcare-settings-layout.yaml'))) as f:
        layout = yaml.load(f)

    for section in layout:
        # i18n; not statically analyzable
        section['title'] = ugettext_noop(section['title'])
        for i, key in enumerate(section['settings']):
            setting = settings.pop(key)
            if doc_type == 'Application' or setting['type'] == 'hq':
                section['settings'][i] = setting
            else:
                section['settings'][i] = None
        section['settings'] = filter(None, section['settings'])
        for setting in section['settings']:
            setting['value'] = None

    if settings:
        raise Exception("CommCare settings layout should mention "
                        "all the available settings. "
                        "The following settings went unmentioned: %s" %
                        (', '.join(settings.keys())))
    return layout
Exemplo n.º 13
0
def import_app(request, domain):
    template = get_app_manager_template(
        domain,
        "app_manager/v1/import_app.html",
        "app_manager/v2/import_app.html",
    )
    if request.method == "POST":
        clear_app_cache(request, domain)
        name = request.POST.get('name')
        compressed = request.POST.get('compressed')

        valid_request = True
        if not name:
            messages.error(request, _("You must submit a name for the application you are importing."))
            valid_request = False
        if not compressed:
            messages.error(request, _("You must submit the source data."))
            valid_request = False

        if not valid_request:
            return render(request, template, {'domain': domain})

        source = decompress([chr(int(x)) if int(x) < 256 else int(x) for x in compressed.split(',')])
        source = json.loads(source)
        assert(source is not None)
        app = import_app_util(source, domain, {'name': name})

        return back_to_main(request, domain, app_id=app._id)
    else:
        app_id = request.GET.get('app')
        redirect_domain = request.GET.get('domain') or None
        if redirect_domain is not None:
            redirect_domain = redirect_domain.lower()
            if Domain.get_by_name(redirect_domain):
                return HttpResponseRedirect(
                    reverse('import_app', args=[redirect_domain])
                    + "?app={app_id}".format(app_id=app_id)
                )
            else:
                if redirect_domain:
                    messages.error(request, "We can't find a project called %s." % redirect_domain)
                else:
                    messages.error(request, "You left the project name blank.")
                return HttpResponseRedirect(request.META.get('HTTP_REFERER', request.path))

        if app_id:
            app = get_app(None, app_id)
            assert(app.get_doc_type() in ('Application', 'RemoteApp'))
            assert(request.couch_user.is_member_of(app.domain))
        else:
            app = None

        return render(request, template, {
            'domain': domain,
            'app': app,
        })
Exemplo n.º 14
0
def releases_ajax(request, domain, app_id):
    template = get_app_manager_template(
        request.user,
        "app_manager/v1/partials/releases.html",
        "app_manager/v2/partials/releases.html",
    )
    context = get_releases_context(request, domain, app_id)
    response = render(request, template, context)
    response.set_cookie('lang', encode_if_unicode(context['lang']))
    return response
Exemplo n.º 15
0
def validate_form_for_build(request,
                            domain,
                            app_id,
                            unique_form_id,
                            ajax=True):
    app = get_app(domain, app_id)
    try:
        form = app.get_form(unique_form_id)
    except FormNotFoundException:
        # this can happen if you delete the form from another page
        raise Http404()
    errors = form.validate_for_build()
    lang, langs = get_langs(request, app)

    if ajax and "blank form" in [error.get('type') for error in errors
                                 ] and not form.form_type == "shadow_form":
        response_html = ("" if toggles.APP_MANAGER_V2.enabled(
            request.user.username) else render_to_string(
                'app_manager/v1/partials/create_form_prompt.html'))
    else:
        if form.form_type == "shadow_form":
            # Don't display the blank form error if its a shadow form
            errors = [e for e in errors if e['type'] != "blank form"]
        response_html = render_to_string(
            get_app_manager_template(
                request.user,
                'app_manager/v1/partials/build_errors.html',
                'app_manager/v2/partials/build_errors.html',
            ), {
                'request': request,
                'app': app,
                'form': form,
                'build_errors': errors,
                'not_actual_build': True,
                'domain': domain,
                'langs': langs,
                'lang': lang
            })

    if ajax:
        return json_response({
            'error_html': response_html,
        })
    else:
        return HttpResponse(response_html)
Exemplo n.º 16
0
def _load_commcare_settings_layout(doc_type, domain):
    settings = dict([
        ('{0}.{1}'.format(setting.get('type'), setting.get('id')), setting)
        for setting in _load_custom_commcare_settings(domain)
    ])
    path = os.path.join(os.path.dirname(__file__), 'static', 'app_manager', 'json')
    with open(os.path.join(
            path,
            get_app_manager_template(
                domain,
                'v1/commcare-settings-layout.yaml',
                'v2/commcare-settings-layout.yaml'
            ))) as f:
        layout = yaml.load(f)

    for section in layout:
        # i18n; not statically analyzable
        section['title'] = ugettext_noop(section['title'])
        for i, key in enumerate(section['settings']):
            setting = settings.pop(key)
            if doc_type == 'Application' or setting['type'] == 'hq':
                section['settings'][i] = setting
            else:
                section['settings'][i] = None
        section['settings'] = filter(None, section['settings'])
        for setting in section['settings']:
            setting['value'] = None

    if settings:
        raise Exception(
            "CommCare settings layout should mention "
            "all the available settings. "
            "The following settings went unmentioned: %s" % (
                ', '.join(settings.keys())
            )
        )
    return layout
Exemplo n.º 17
0
def xform_display(request, domain, form_unique_id):
    try:
        form, app = Form.get_form(form_unique_id, and_app=True)
    except ResourceNotFound:
        raise Http404()
    if domain != app.domain:
        raise Http404()
    langs = [request.GET.get('lang')] + app.langs

    questions = form.get_questions(langs,
                                   include_triggers=True,
                                   include_groups=True)

    if request.GET.get('format') == 'html':
        questions = [FormQuestionResponse(q) for q in questions]
        template = get_app_manager_template(
            request.user,
            'app_manager/v1/xform_display.html',
            'app_manager/v2/xform_display.html',
        )
        return render(request, template,
                      {'questions': questions_in_hierarchy(questions)})
    else:
        return json_response(questions)
Exemplo n.º 18
0
def view_generic(request,
                 domain,
                 app_id=None,
                 module_id=None,
                 form_id=None,
                 copy_app_form=None,
                 release_manager=False):
    """
    This is the main view for the app. All other views redirect to here.

    """
    if form_id and not module_id:
        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()
        if form_id:
            try:
                form = module.get_form(form_id)
            except IndexError:
                raise Http404()
    except ModuleNotFoundException:
        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
            })
            template = get_app_manager_template(
                request.user,
                'app_manager/v1/no_longer_supported.html',
                'app_manager/v2/no_longer_supported.html',
            )
            return render(request, template, {
                '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 toggles.USER_PROPERTY_EASY_REFS.enabled(domain)
                and "usercase_preload" in 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,
                    'form_id': form_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 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))

        v2_template = ('app_manager/v2/app_view_release_manager.html'
                       if release_manager else
                       'app_manager/v2/app_view_settings.html')

        template = get_app_manager_template(request.user,
                                            'app_manager/v1/app_view.html',
                                            v2_template)

        if release_manager:
            context.update(get_releases_context(request, domain, app_id))
        context.update({
            'is_app_settings_page': not release_manager,
        })
    else:
        if toggles.APP_MANAGER_V2.enabled(request.user.username):
            from corehq.apps.dashboard.views import DomainDashboardView
            return HttpResponseRedirect(
                reverse(DomainDashboardView.urlname, args=[domain]))
        else:
            from corehq.apps.dashboard.views import NewUserDashboardView
            return HttpResponseRedirect(
                reverse(NewUserDashboardView.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_id:
            default_file_name = '%s_form%s' % (default_file_name, form_id)

        specific_media = {
            'menu': {
                '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 module 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['case_list_form'] = {
                'menu_refs':
                app.get_case_list_form_media(module,
                                             module_id,
                                             to_language=lang),
                'default_file_name':
                _make_name('case_list_form'),
            }
            specific_media['case_list_menu_item'] = {
                'menu_refs':
                app.get_case_list_menu_item_media(module,
                                                  module_id,
                                                  to_language=lang),
                'default_file_name':
                _make_name('case_list_menu_item'),
            }
            specific_media['case_list_lookup'] = {
                'menu_refs':
                app.get_case_list_lookup_image(module, module_id),
                'default_file_name':
                '{}_case_list_lookup'.format(default_file_name),
            }

            if hasattr(module, 'product_details'):
                specific_media['product_list_lookup'] = {
                    'menu_refs':
                    app.get_case_list_lookup_image(module,
                                                   module_id,
                                                   type='product'),
                    'default_file_name':
                    '{}_product_list_lookup'.format(default_file_name),
                }

        context.update({
            'multimedia': {
                "object_map": app.get_object_map(),
                'upload_managers': {
                    'icon':
                    MultimediaImageUploadController(
                        "hqimage",
                        reverse(ProcessImageFileUploadView.name,
                                args=[app.domain, app.get_id])),
                    'audio':
                    MultimediaAudioUploadController(
                        "hqaudio",
                        reverse(ProcessAudioFileUploadView.name,
                                args=[app.domain, app.get_id])),
                },
            }
        })
        try:
            context['multimedia']['references'] = app.get_references()
        except ReportConfigurationNotFoundError:
            pass
        context['multimedia'].update(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]

    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)
            },
        })

    domain_obj = Domain.get_by_name(domain)
    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')
    })

    response = render(request, template, context)

    response.set_cookie('lang', encode_if_unicode(lang))
    return response
Exemplo n.º 19
0
def form_designer(request, domain, app_id, module_id=None, form_id=None):
    def _form_uses_case(module, form):
        return module and module.case_type and form.requires_case()

    def _form_is_basic(form):
        return form.doc_type == 'Form'

    def _form_too_large(app, form):
        # form less than 0.1MB, anything larger starts to have
        # performance issues with fullstory
        return app.blobs['{}.xml'.format(
            form.unique_id)]['content_length'] > 102400

    meta = get_meta(request)
    track_entered_form_builder_on_hubspot.delay(request.couch_user,
                                                request.COOKIES, meta)

    app = get_app(domain, app_id)
    module = None

    try:
        module = app.get_module(module_id)
    except ModuleNotFoundException:
        return bail(request, domain, app_id, not_found="module")
    try:
        form = module.get_form(form_id)
    except IndexError:
        return bail(request, domain, app_id, not_found="form")

    if form.no_vellum:
        messages.warning(
            request,
            _("You tried to edit this form in the Form Builder. "
              "However, your administrator has locked this form against editing "
              "in the form builder, so we have redirected you to "
              "the form's front page instead."))
        return back_to_main(request,
                            domain,
                            app_id=app_id,
                            unique_form_id=form.unique_id)

    include_fullstory = False
    vellum_plugins = ["modeliteration", "itemset", "atwho"]
    if (toggles.COMMTRACK.enabled(domain)):
        vellum_plugins.append("commtrack")
    if toggles.VELLUM_SAVE_TO_CASE.enabled(domain):
        vellum_plugins.append("saveToCase")
    if (_form_uses_case(module, form) and _form_is_basic(form)):
        vellum_plugins.append("databrowser")

    vellum_features = toggles.toggles_dict(username=request.user.username,
                                           domain=domain)
    vellum_features.update(feature_previews.previews_dict(domain))
    include_fullstory = not _form_too_large(app, form)
    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,
    })

    has_schedule = (getattr(module, 'has_schedule', False)
                    and getattr(form, 'schedule', False)
                    and form.schedule.enabled)
    scheduler_data_nodes = []
    if has_schedule:
        scheduler_data_nodes = [
            SCHEDULE_CURRENT_VISIT_NUMBER,
            SCHEDULE_NEXT_DUE,
            SCHEDULE_UNSCHEDULED_VISIT,
            SCHEDULE_GLOBAL_NEXT_VISIT_DATE,
        ]
        scheduler_data_nodes.extend([
            u"next_{}".format(f.schedule_form_id)
            for f in form.get_phase().get_forms()
            if getattr(f, 'schedule', False) and f.schedule.enabled
        ])

    if tours.VELLUM_CASE_MANAGEMENT.is_enabled(
            request.user) and form.requires_case():
        request.guided_tour = tours.VELLUM_CASE_MANAGEMENT.get_tour_data()

    context = get_apps_base_context(request, domain, app)
    context.update(locals())
    context.update({
        'vellum_debug':
        settings.VELLUM_DEBUG,
        'nav_form':
        form,
        'formdesigner':
        True,
        'include_fullstory':
        include_fullstory,
        'notifications_enabled':
        request.user.is_superuser,
        'notify_facility':
        get_facility_for_form(domain, app_id, form.unique_id),
    })
    notify_form_opened(domain, request.couch_user, app_id, form.unique_id)

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

    core = {
        'dataSourcesEndpoint':
        reverse('get_form_data_schema',
                kwargs={
                    'domain': domain,
                    'form_unique_id': form.get_unique_id()
                }),
        'dataSource': [
            # DEPRECATED. Use dataSourcesEndpoint
            {
                'key': 'fixture',
                'name': 'Fixtures',
                'endpoint': reverse('fixture_metadata',
                                    kwargs={'domain': domain}),
            },
        ],
        'form':
        form.source,
        'formId':
        form.get_unique_id(),
        'formName':
        trans(form.name, app.langs),
        'saveType':
        'patch',
        'saveUrl':
        reverse('edit_form_attr',
                args=[domain, app.id,
                      form.get_unique_id(), 'xform']),
        'patchUrl':
        reverse('patch_xform', args=[domain, app.id,
                                     form.get_unique_id()]),
        'allowedDataNodeReferences': [
            "meta/deviceID",
            "meta/instanceID",
            "meta/username",
            "meta/userID",
            "meta/timeStart",
            "meta/timeEnd",
            "meta/location",
        ] + scheduler_data_nodes,
        'activityUrl':
        reverse('ping'),
        'sessionid':
        request.COOKIES.get('sessionid'),
        'externalLinks': {
            'changeSubscription':
            reverse("domain_subscription_view", kwargs={'domain': domain}),
        },
        'invalidCaseProperties': ['name'],
    }

    if toggles.APP_MANAGER_V2.enabled(request.user.username):
        if form.get_action_type() == 'open':
            core.update({
                'defaultHelpTextTemplateId': '#fd-hq-helptext-registration',
                'formIconClass': 'fcc fcc-app-createform',
            })
        elif form.get_action_type() == 'close':
            core.update({
                'defaultHelpTextTemplateId': '#fd-hq-helptext-close',
                'formIconClass': 'fcc fcc-app-completeform',
            })
        elif form.get_action_type() == 'update':
            core.update({
                'defaultHelpTextTemplateId': '#fd-hq-helptext-followup',
                'formIconClass': 'fcc fcc-app-updateform',
            })
        else:
            core.update({
                'defaultHelpTextTemplateId': '#fd-hq-helptext-survey',
                'formIconClass': 'fa fa-file-o',
            })

    vellum_options = {
        'core': core,
        'plugins': vellum_plugins,
        'features': vellum_features,
        'intents': {
            'templates': next(app_callout_templates),
        },
        'javaRosa': {
            'langs': app.langs,
            'displayLanguage': context['lang'],
        },
        'uploader': {
            'uploadUrls': {
                'image': reverse("hqmedia_uploader_image",
                                 args=[domain, app.id]),
                'audio': reverse("hqmedia_uploader_audio",
                                 args=[domain, app.id]),
                'video': reverse("hqmedia_uploader_video",
                                 args=[domain, app.id]),
                'text': reverse("hqmedia_uploader_text", args=[domain,
                                                               app.id]),
            },
            'objectMap': app.get_object_map(),
            'sessionid': request.COOKIES.get('sessionid'),
        },
    }
    context.update({
        'vellum_options': vellum_options,
        'CKEDITOR_BASEPATH': "app_manager/js/vellum/lib/ckeditor/",
    })

    if not settings.VELLUM_DEBUG:
        context.update({'requirejs_url': "app_manager/js/vellum/src"})
    elif settings.VELLUM_DEBUG == "dev-min":
        context.update({'requirejs_url': "formdesigner/_build/src"})
    else:
        context.update({'requirejs_url': "formdesigner/src"})
    context.update({
        'requirejs_args':
        'version={}{}'.format(
            cachebuster("app_manager/js/vellum/src/main-components.js"),
            cachebuster("app_manager/js/vellum/src/local-deps.js")),
    })

    template = get_app_manager_template(
        request.user,
        'app_manager/v1/form_designer.html',
        'app_manager/v2/form_designer.html',
    )

    response = render(request, template, context)
    return response
Exemplo n.º 20
0
def direct_ccz(request, domain):
    """
    You must specify an app_id, and you may specify either 'version' or 'latest'
    latest can be one of:
        release: Latest starred version
        build: Latest version regardless of star
        save: Latest saved version of the application (even without a build)
    If 'version' and 'latest' aren't specified it will default to latest save
    You may also set 'include_multimedia=true' if you need multimedia.
    """
    def error(msg, code=400):
        return json_response({
            'status': 'error',
            'message': msg
        },
                             status_code=code)

    def get_app(app_id, version, latest):
        if version:
            return get_build_doc_by_version(domain, app_id, version)
        elif latest == 'build':
            return get_latest_build_doc(domain, app_id)
        elif latest == 'release':
            return get_latest_released_app_doc(domain, app_id)
        else:
            # either latest=='save' or they didn't specify
            return get_current_app(domain, app_id)

    app_id = request.GET.get('app_id', None)
    version = request.GET.get('version', None)
    latest = request.GET.get('latest', None)
    include_multimedia = request.GET.get('include_multimedia',
                                         'false').lower() == 'true'

    # Make sure URL params make sense
    if not app_id:
        return error("You must specify `app_id` in your GET parameters")
    if version and latest:
        return error("You can't specify both 'version' and 'latest'")
    if latest not in (
            None,
            'release',
            'build',
            'save',
    ):
        return error("latest must be either 'release', 'build', or 'save'")
    if version:
        try:
            version = int(version)
        except ValueError:
            return error("'version' must be an integer")

    try:
        app = get_app(app_id, version, latest)
        if not app:
            raise ResourceNotFound()
        app = app if isinstance(app, Document) else wrap_app(app)
    except (ResourceNotFound, DocTypeError):
        return error("Application not found", code=404)

    if not app.copy_of:
        errors = app.validate_app()
    else:
        errors = None

    if errors:
        lang, langs = get_langs(request, app)
        template = get_app_manager_template(
            domain, 'app_manager/v1/partials/build_errors.html',
            'app_manager/v2/partials/build_errors.html')
        error_html = render_to_string(
            template, {
                'request': request,
                'app': app,
                'build_errors': errors,
                'domain': domain,
                'langs': langs,
                'lang': lang
            })
        return json_response(
            {'error_html': error_html},
            status_code=400,
        )

    app.set_media_versions(None)
    download = DownloadBase()
    errors = build_application_zip(
        include_multimedia_files=include_multimedia,
        include_index_files=True,
        app=app,
        download_id=download.download_id,
        compress_zip=True,
        filename='{}.ccz'.format(slugify(app.name)),
    )

    if errors is not None and errors['errors']:
        return json_response(
            errors,
            status_code=400,
        )
    return DownloadBase.get(download.download_id).toHttpResponse()
Exemplo n.º 21
0
def form_designer(request, domain, app_id, module_id=None, form_id=None):
    def _form_uses_case(module, form):
        return module and module.case_type and form.requires_case()

    def _form_is_basic(form):
        return form.doc_type == 'Form'

    def _form_too_large(app, form):
        # form less than 0.1MB, anything larger starts to have
        # performance issues with fullstory
        return app.blobs['{}.xml'.format(
            form.unique_id)]['content_length'] > 102400

    meta = get_meta(request)
    track_entered_form_builder_on_hubspot.delay(request.couch_user,
                                                request.COOKIES, meta)

    app = get_app(domain, app_id)
    module = None

    try:
        module = app.get_module(module_id)
    except ModuleNotFoundException:
        return bail(request, domain, app_id, not_found="module")
    try:
        form = module.get_form(form_id)
    except IndexError:
        return bail(request, domain, app_id, not_found="form")

    if form.no_vellum:
        messages.warning(
            request,
            _("You tried to edit this form in the Form Builder. "
              "However, your administrator has locked this form against editing "
              "in the form builder, so we have redirected you to "
              "the form's front page instead."))
        return back_to_main(request,
                            domain,
                            app_id=app_id,
                            unique_form_id=form.unique_id)

    include_fullstory = False
    vellum_plugins = ["modeliteration", "itemset", "atwho"]
    if (toggles.COMMTRACK.enabled(domain)):
        vellum_plugins.append("commtrack")
    if toggles.VELLUM_SAVE_TO_CASE.enabled(domain):
        vellum_plugins.append("saveToCase")
    if (_form_uses_case(module, form) and _form_is_basic(form)):
        vellum_plugins.append("databrowser")

    vellum_features = toggles.toggles_dict(username=request.user.username,
                                           domain=domain)
    vellum_features.update(feature_previews.previews_dict(domain))
    include_fullstory = not _form_too_large(app, form)
    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,
    })

    has_schedule = (getattr(module, 'has_schedule', False)
                    and getattr(form, 'schedule', False)
                    and form.schedule.enabled)
    scheduler_data_nodes = []
    if has_schedule:
        scheduler_data_nodes = [
            SCHEDULE_CURRENT_VISIT_NUMBER,
            SCHEDULE_NEXT_DUE,
            SCHEDULE_UNSCHEDULED_VISIT,
            SCHEDULE_GLOBAL_NEXT_VISIT_DATE,
        ]
        scheduler_data_nodes.extend([
            u"next_{}".format(f.schedule_form_id)
            for f in form.get_phase().get_forms()
            if getattr(f, 'schedule', False) and f.schedule.enabled
        ])

    if tours.VELLUM_CASE_MANAGEMENT.is_enabled(
            request.user) and form.requires_case():
        request.guided_tour = tours.VELLUM_CASE_MANAGEMENT.get_tour_data()

    vellum_base = 'corehq/apps/app_manager/static/app_manager/js/'
    vellum_dir = 'vellum'
    if isdir(join(vellum_base, 'vellum_beta')):
        vellum_dir = 'vellum_beta'

    context = get_apps_base_context(request, domain, app)
    context.update(locals())
    context.update({
        'vellum_debug':
        settings.VELLUM_DEBUG,
        'nav_form':
        form,
        'vellum_style_path':
        'app_manager/js/{}/style.css'.format(vellum_dir),
        'vellum_ckeditor_path':
        'app_manager/js/{}/lib/ckeditor/'.format(vellum_dir),
        'vellum_js_path':
        'app_manager/js/{}/src'.format(vellum_dir),
        'vellum_main_components_path':
        'app_manager/js/{}/src/main-components.js'.format(vellum_dir),
        'vellum_local_deps_path':
        'app_manager/js/{}/src/local-deps.js'.format(vellum_dir),
        'formdesigner':
        True,
        'multimedia_object_map':
        app.get_object_map(),
        'sessionid':
        request.COOKIES.get('sessionid'),
        'features':
        vellum_features,
        'plugins':
        vellum_plugins,
        'app_callout_templates':
        next(app_callout_templates),
        'scheduler_data_nodes':
        scheduler_data_nodes,
        'include_fullstory':
        include_fullstory,
        'notifications_enabled':
        request.user.is_superuser,
        'notify_facility':
        get_facility_for_form(domain, app_id, form.unique_id),
    })
    notify_form_opened(domain, request.couch_user, app_id, form.unique_id)

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

    template = get_app_manager_template(
        domain,
        'app_manager/v1/form_designer.html',
        'app_manager/v2/form_designer.html',
    )

    response = render(request, template, context)
    return response
Exemplo n.º 22
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 (attachemnts) until MM Case Properties
            # are released to general public
            is_previewer = toggles.MM_CASE_PROPERTIES.enabled(
                request.user.username)
            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
            })

    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 form.get_module().has_schedule
    case_config_options = {
        'caseType': form.get_case_type(),
        'moduleCaseTypes': module_case_types,
        'propertiesMap': get_all_case_properties(app),
        'questions': xform_questions,
        'reserved_words': load_case_reserved_words(),
    }
    context = {
        'nav_form':
        form,
        'xform_languages':
        languages,
        "xform_questions":
        xform_questions,
        'form_errors':
        form_errors,
        'xform_validation_errored':
        xform_validation_errored,
        'xform_validation_missing':
        xform_validation_missing,
        'allow_cloudcare':
        isinstance(form, Form),
        'allow_form_copy':
        isinstance(form, (Form, AdvancedForm)),
        'allow_form_filtering':
        not isinstance(form, CareplanForm) and not form_has_schedule,
        'allow_form_workflow':
        not isinstance(form, CareplanForm),
        '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,
        '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']),
        'case_xpath_pattern_matches':
        CASE_XPATH_PATTERN_MATCHES,
        'case_xpath_substring_matches':
        CASE_XPATH_SUBSTRING_MATCHES,
        'user_case_xpath_pattern_matches':
        USER_CASE_XPATH_PATTERN_MATCHES,
        'user_case_xpath_substring_matches':
        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')
    }

    if tours.NEW_APP.is_enabled(
            request.user) and not toggles.APP_MANAGER_V2.enabled(
                request.user.username):
        request.guided_tour = tours.NEW_APP.get_tour_data()

    if context['allow_form_workflow'] and toggles.FORM_LINK_WORKFLOW.enabled(
            domain):
        module = form.get_module()

        def qualified_form_name(form, auto_link):
            module_name = trans(form.get_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, CareplanForm):
        case_config_options.update({
            'save_url':
            reverse("edit_careplan_form_actions",
                    args=[app.domain, app.id, module.id, form.id]),
            'case_preload': [{
                'key': key,
                'path': path
            } for key, path in form.case_preload.items()],
            'customCaseUpdates': [{
                'key': key,
                'path': path
            } for key, path in form.custom_case_updates.items()],
            'fixedQuestions':
            form.get_fixed_questions(),
            'mode':
            form.mode,
        })
    elif 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({
            'save_url':
            reverse("edit_advanced_form_actions",
                    args=[app.domain, app.id, module.id, form.id]),
            'commtrack_enabled':
            app.commtrack_enabled,
            'commtrack_programs':
            all_programs + commtrack_programs(),
            'module_id':
            module.unique_id,
            'propertyDescriptions':
            get_case_property_description_dict(domain),
        })
        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 module.has_schedule:
            visit_scheduler_options = get_schedule_context(form)
            visit_scheduler_options.update({
                'questions':
                xform_questions,
                'save_url':
                reverse("edit_visit_schedule",
                        args=[app.domain, app.id, module.id, form.id]),
                'schedule':
                form.schedule,
                'phase':
                visit_scheduler_options['schedule_phase'],
            })
            context.update(
                {'visit_scheduler_options': visit_scheduler_options})
    else:
        case_config_options.update({
            'actions':
            form.actions,
            'allowUsercase':
            allow_usercase,
            'valid_index_names':
            valid_index_names,
            'usercasePropertiesMap':
            get_usercase_properties(app),
            'propertyDescriptions':
            get_case_property_description_dict(domain),
            'save_url':
            reverse("edit_form_actions",
                    args=[app.domain, app.id, module.id, form.id]),
        })
        context.update({
            'show_custom_ref':
            toggles.APP_BUILDER_CUSTOM_PARENT_REF.enabled_for_request(request),
        })
    context.update({'case_config_options': case_config_options})
    template = get_app_manager_template(
        request.user,
        "app_manager/v1/form_view.html",
        "app_manager/v2/form_view.html",
    )
    return template, context