Beispiel #1
0
    def validate_with_raise(self):
        errors = super(ModuleValidator, self).validate_with_raise()
        errors += self.validate_details_for_build()
        if not self.module.forms and not self.module.case_list.show:
            errors.append({
                'type': 'no forms or case list',
                'module': self.get_module_info(),
            })

        if module_case_hierarchy_has_circular_reference(self.module):
            errors.append({
                'type': 'circular case hierarchy',
                'module': self.get_module_info(),
            })

        if self.module.root_module and self.module.root_module.is_training_module:
            errors.append({
                'type': 'training module parent',
                'module': self.get_module_info(),
            })

        if self.module.root_module and self.module.is_training_module:
            errors.append({
                'type': 'training module child',
                'module': self.get_module_info(),
            })

        return errors
Beispiel #2
0
    def validate_with_raise(self):
        errors = super(ModuleValidator, self).validate_with_raise()
        errors += self.validate_details_for_build()
        if not self.module.forms and not self.module.case_list.show:
            errors.append({
                'type': 'no forms or case list',
                'module': self.get_module_info(),
            })

        if module_case_hierarchy_has_circular_reference(self.module):
            errors.append({
                'type': 'circular case hierarchy',
                'module': self.get_module_info(),
            })

        if self.module.root_module and self.module.root_module.is_training_module:
            errors.append({
                'type': 'training module parent',
                'module': self.get_module_info(),
            })

        if self.module.root_module and self.module.is_training_module:
            errors.append({
                'type': 'training module child',
                'module': self.get_module_info(),
            })

        return errors
Beispiel #3
0
def edit_module_detail_screens(request, domain, app_id, module_id):
    """
    Overwrite module case details. Only overwrites components that have been
    provided in the request. Components are short, long, filter, parent_select,
    fixture_select and sort_elements.
    """
    params = json_request(request.POST)
    detail_type = params.get('type')
    short = params.get('short', None)
    long = params.get('long', None)
    tabs = params.get('tabs', None)
    filter = params.get('filter', ())
    custom_xml = params.get('custom_xml', None)
    parent_select = params.get('parent_select', None)
    fixture_select = params.get('fixture_select', None)
    sort_elements = params.get('sort_elements', None)
    persist_case_context = params.get('persistCaseContext', None)
    persistent_case_context_xml = params.get('persistentCaseContextXML', None)
    use_case_tiles = params.get('useCaseTiles', None)
    persist_tile_on_forms = params.get("persistTileOnForms", None)
    pull_down_tile = params.get("enableTilePullDown", None)
    case_list_lookup = params.get("case_list_lookup", None)
    search_properties = params.get("search_properties")
    custom_variables = {
        'short': params.get("short_custom_variables", None),
        'long': params.get("long_custom_variables", None)
    }

    app = get_app(domain, app_id)
    module = app.get_module(module_id)

    if detail_type == 'case':
        detail = module.case_details
    elif detail_type == CAREPLAN_GOAL:
        detail = module.goal_details
    elif detail_type == CAREPLAN_TASK:
        detail = module.task_details
    else:
        try:
            detail = getattr(module, '{0}_details'.format(detail_type))
        except AttributeError:
            return HttpResponseBadRequest("Unknown detail type '%s'" %
                                          detail_type)

    lang = request.COOKIES.get('lang', app.langs[0])
    if short is not None:
        detail.short.columns = map(DetailColumn.from_json, short)
        if persist_case_context is not None:
            detail.short.persist_case_context = persist_case_context
            detail.short.persistent_case_context_xml = persistent_case_context_xml
        if use_case_tiles is not None:
            detail.short.use_case_tiles = use_case_tiles
        if persist_tile_on_forms is not None:
            detail.short.persist_tile_on_forms = persist_tile_on_forms
        if pull_down_tile is not None:
            detail.short.pull_down_tile = pull_down_tile
        if case_list_lookup is not None:
            _save_case_list_lookup_params(detail.short, case_list_lookup, lang)

    if long is not None:
        detail.long.columns = map(DetailColumn.from_json, long)
        if tabs is not None:
            detail.long.tabs = map(DetailTab.wrap, tabs)
    if filter != ():
        # Note that we use the empty tuple as the sentinel because a filter
        # value of None represents clearing the filter.
        detail.short.filter = filter
    if custom_xml is not None:
        detail.short.custom_xml = custom_xml

    if custom_variables['short'] is not None:
        try:
            etree.fromstring("<variables>{}</variables>".format(
                custom_variables['short']))
        except etree.XMLSyntaxError as error:
            return HttpResponseBadRequest(
                "There was an issue with your custom variables: {}".format(
                    error.message))
        detail.short.custom_variables = custom_variables['short']

    if custom_variables['long'] is not None:
        try:
            etree.fromstring("<variables>{}</variables>".format(
                custom_variables['long']))
        except etree.XMLSyntaxError as error:
            return HttpResponseBadRequest(
                "There was an issue with your custom variables: {}".format(
                    error.message))
        detail.long.custom_variables = custom_variables['long']

    if sort_elements is not None:
        detail.short.sort_elements = []
        for sort_element in sort_elements:
            item = SortElement()
            item.field = sort_element['field']
            item.type = sort_element['type']
            item.direction = sort_element['direction']
            item.display[lang] = sort_element['display']
            if toggles.SORT_CALCULATION_IN_CASE_LIST.enabled(domain):
                item.sort_calculation = sort_element['sort_calculation']
            else:
                item.sort_calculation = ""
            detail.short.sort_elements.append(item)
    if parent_select is not None:
        module.parent_select = ParentSelect.wrap(parent_select)
        if module_case_hierarchy_has_circular_reference(module):
            return HttpResponseBadRequest(
                _("The case hierarchy contains a circular reference."))
    if fixture_select is not None:
        module.fixture_select = FixtureSelect.wrap(fixture_select)
    if search_properties is not None:
        if search_properties.get('properties') is not None:
            module.search_config = CaseSearch(
                properties=[
                    CaseSearchProperty.wrap(p)
                    for p in _update_search_properties(
                        module, search_properties.get('properties'), lang)
                ],
                relevant=(search_properties.get('relevant')
                          if search_properties.get('relevant') is not None else
                          CLAIM_DEFAULT_RELEVANT_CONDITION),
                include_closed=bool(search_properties.get('include_closed')),
                default_properties=[
                    DefaultCaseSearchProperty.wrap(p)
                    for p in search_properties.get('default_properties')
                ])

    resp = {}
    app.save(resp)
    return json_response(resp)
Beispiel #4
0
def edit_module_attr(request, domain, app_id, module_id, attr):
    """
    Called to edit any (supported) module attribute, given by attr
    """
    attributes = {
        "all": None,
        "auto_select_case": None,
        "case_label": 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_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,
        "referral_label": None,
        "root_module_id": None,
        "source_module_id": None,
        "task_list": ('task_list-show', 'task_list-label'),
        "excl_form_ids": None,
        "display_style": 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)
    module = app.get_module(module_id)
    lang = request.COOKIES.get('lang', app.langs[0])
    resp = {'update': {}, 'corrections': {}}
    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
            other_careplan_modules = []
            all_advanced_modules = []
            modules_with_old_case_type_exist = False
            for mod in app.modules:
                if mod.unique_id != module_id:
                    if isinstance(mod, CareplanModule):
                        other_careplan_modules.append(mod)

                if isinstance(mod, AdvancedModule):
                    all_advanced_modules.append(mod)

                modules_with_old_case_type_exist |= mod.case_type == old_case_type

            for cp_mod in other_careplan_modules:
                if cp_mod.parent_select.module_id == module_id:
                    cp_mod.case_type = 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_id:
                            action.case_type = case_type

                    if mod.unique_id == module_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_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)

    for attribute in ("name", "case_label", "referral_label"):
        if should_edit(attribute):
            name = request.POST.get(attribute, None)
            module[attribute][lang] = name
            if should_edit("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"):
        if not request.POST.get("root_module_id"):
            module["root_module_id"] = None
        else:
            try:
                app.get_module(module_id)
                module["root_module_id"] = request.POST.get("root_module_id")
            except ModuleNotFoundException:
                messages.error(_("Unknown Menu"))

    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))
Beispiel #5
0
def edit_module_detail_screens(request, domain, app_id, module_unique_id):
    """
    Overwrite module case details. Only overwrites components that have been
    provided in the request. Components are short, long, filter, parent_select,
    fixture_select and sort_elements.
    """
    params = json_request(request.POST)
    detail_type = params.get('type')
    short = params.get('short', None)
    long_ = params.get('long', None)
    tabs = params.get('tabs', None)
    filter = params.get('filter', ())
    custom_xml = params.get('custom_xml', None)
    parent_select = params.get('parent_select', None)
    fixture_select = params.get('fixture_select', None)
    sort_elements = params.get('sort_elements', None)
    persist_case_context = params.get('persistCaseContext', None)
    persistent_case_context_xml = params.get('persistentCaseContextXML', None)
    use_case_tiles = params.get('useCaseTiles', None)
    persist_tile_on_forms = params.get("persistTileOnForms", None)
    persistent_case_tile_from_module = params.get("persistentCaseTileFromModule", None)
    pull_down_tile = params.get("enableTilePullDown", None)
    sort_nodeset_columns = params.get("sortNodesetColumns", None)
    print_template = params.get('printTemplate', None)
    case_list_lookup = params.get("case_list_lookup", None)
    search_properties = params.get("search_properties")
    custom_variables = {
        'short': params.get("short_custom_variables", None),
        'long': params.get("long_custom_variables", 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)

    if detail_type == 'case':
        detail = module.case_details
    else:
        try:
            detail = getattr(module, '{0}_details'.format(detail_type))
        except AttributeError:
            return HttpResponseBadRequest("Unknown detail type '%s'" % detail_type)

    lang = request.COOKIES.get('lang', app.langs[0])
    if short is not None:
        detail.short.columns = list(map(DetailColumn.from_json, short))
        if persist_case_context is not None:
            detail.short.persist_case_context = persist_case_context
            detail.short.persistent_case_context_xml = persistent_case_context_xml
        if use_case_tiles is not None:
            detail.short.use_case_tiles = use_case_tiles
        if persist_tile_on_forms is not None:
            detail.short.persist_tile_on_forms = persist_tile_on_forms
        if persistent_case_tile_from_module is not None:
            detail.short.persistent_case_tile_from_module = persistent_case_tile_from_module
        if pull_down_tile is not None:
            detail.short.pull_down_tile = pull_down_tile
        if case_list_lookup is not None:
            _save_case_list_lookup_params(detail.short, case_list_lookup, lang)

    if long_ is not None:
        detail.long.columns = list(map(DetailColumn.from_json, long_))
        if tabs is not None:
            detail.long.tabs = list(map(DetailTab.wrap, tabs))
        if print_template is not None:
            detail.long.print_template = print_template
    if filter != ():
        # Note that we use the empty tuple as the sentinel because a filter
        # value of None represents clearing the filter.
        detail.short.filter = filter
    if custom_xml is not None:
        detail.short.custom_xml = custom_xml

    if custom_variables['short'] is not None:
        try:
            etree.fromstring("<variables>{}</variables>".format(custom_variables['short']))
        except etree.XMLSyntaxError as error:
            return HttpResponseBadRequest(
                "There was an issue with your custom variables: {}".format(error.message)
            )
        detail.short.custom_variables = custom_variables['short']

    if custom_variables['long'] is not None:
        try:
            etree.fromstring("<variables>{}</variables>".format(custom_variables['long']))
        except etree.XMLSyntaxError as error:
            return HttpResponseBadRequest(
                "There was an issue with your custom variables: {}".format(error.message)
            )
        detail.long.custom_variables = custom_variables['long']

    if sort_nodeset_columns is not None:
        detail.long.sort_nodeset_columns = sort_nodeset_columns

    if sort_elements is not None:
        # Attempt to map new elements to old so we don't lose translations
        # Imperfect because the same field may be used multiple times, or user may change field
        old_elements_by_field = {e['field']: e for e in detail.short.sort_elements}

        detail.short.sort_elements = []
        for sort_element in sort_elements:
            item = SortElement()
            item.field = sort_element['field']
            item.type = sort_element['type']
            item.direction = sort_element['direction']
            item.blanks = sort_element['blanks']
            if item.field in old_elements_by_field:
                item.display = old_elements_by_field[item.field].display
            item.display[lang] = sort_element['display']
            if toggles.SORT_CALCULATION_IN_CASE_LIST.enabled(domain):
                item.sort_calculation = sort_element['sort_calculation']
            else:
                item.sort_calculation = ""
            detail.short.sort_elements.append(item)
    if parent_select is not None:
        module.parent_select = ParentSelect.wrap(parent_select)
        if module_case_hierarchy_has_circular_reference(module):
            return HttpResponseBadRequest(_("The case hierarchy contains a circular reference."))
    if fixture_select is not None:
        module.fixture_select = FixtureSelect.wrap(fixture_select)
    if search_properties is not None:
        if (
                search_properties.get('properties') is not None
                or search_properties.get('default_properties') is not None
        ):
            module.search_config = CaseSearch(
                properties=[
                    CaseSearchProperty.wrap(p)
                    for p in _update_search_properties(
                        module,
                        search_properties.get('properties'), lang
                    )
                ],
                relevant=(
                    search_properties.get('relevant')
                    if search_properties.get('relevant') is not None
                    else CLAIM_DEFAULT_RELEVANT_CONDITION
                ),
                include_closed=bool(search_properties.get('include_closed')),
                search_button_display_condition=search_properties.get('search_button_display_condition', ""),
                blacklisted_owner_ids_expression=search_properties.get('blacklisted_owner_ids_expression', ""),
                default_properties=[
                    DefaultCaseSearchProperty.wrap(p)
                    for p in search_properties.get('default_properties')
                ]
            )

    resp = {}
    app.save(resp)
    return json_response(resp)
Beispiel #6
0
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))
Beispiel #7
0
def edit_module_detail_screens(request, domain, app_id, module_id):
    """
    Overwrite module case details. Only overwrites components that have been
    provided in the request. Components are short, long, filter, parent_select,
    fixture_select and sort_elements.
    """
    params = json_request(request.POST)
    detail_type = params.get('type')
    short = params.get('short', None)
    long = params.get('long', None)
    tabs = params.get('tabs', None)
    filter = params.get('filter', ())
    custom_xml = params.get('custom_xml', None)
    parent_select = params.get('parent_select', None)
    fixture_select = params.get('fixture_select', None)
    sort_elements = params.get('sort_elements', None)
    persist_case_context = params.get('persistCaseContext', None)
    persistent_case_context_xml = params.get('persistentCaseContextXML', None)
    use_case_tiles = params.get('useCaseTiles', None)
    persist_tile_on_forms = params.get("persistTileOnForms", None)
    pull_down_tile = params.get("enableTilePullDown", None)
    case_list_lookup = params.get("case_list_lookup", None)
    search_properties = params.get("search_properties")
    custom_variables = {
        'short': params.get("short_custom_variables", None),
        'long': params.get("long_custom_variables", None)
    }

    app = get_app(domain, app_id)
    module = app.get_module(module_id)

    if detail_type == 'case':
        detail = module.case_details
    elif detail_type == CAREPLAN_GOAL:
        detail = module.goal_details
    elif detail_type == CAREPLAN_TASK:
        detail = module.task_details
    else:
        try:
            detail = getattr(module, '{0}_details'.format(detail_type))
        except AttributeError:
            return HttpResponseBadRequest("Unknown detail type '%s'" % detail_type)

    lang = request.COOKIES.get('lang', app.langs[0])
    if short is not None:
        detail.short.columns = map(DetailColumn.from_json, short)
        if persist_case_context is not None:
            detail.short.persist_case_context = persist_case_context
            detail.short.persistent_case_context_xml = persistent_case_context_xml
        if use_case_tiles is not None:
            detail.short.use_case_tiles = use_case_tiles
        if persist_tile_on_forms is not None:
            detail.short.persist_tile_on_forms = persist_tile_on_forms
        if pull_down_tile is not None:
            detail.short.pull_down_tile = pull_down_tile
        if case_list_lookup is not None:
            _save_case_list_lookup_params(detail.short, case_list_lookup, lang)

    if long is not None:
        detail.long.columns = map(DetailColumn.from_json, long)
        if tabs is not None:
            detail.long.tabs = map(DetailTab.wrap, tabs)
    if filter != ():
        # Note that we use the empty tuple as the sentinel because a filter
        # value of None represents clearing the filter.
        detail.short.filter = filter
    if custom_xml is not None:
        detail.short.custom_xml = custom_xml

    if custom_variables['short'] is not None:
        try:
            etree.fromstring("<variables>{}</variables>".format(custom_variables['short']))
        except etree.XMLSyntaxError as error:
            return HttpResponseBadRequest(
                "There was an issue with your custom variables: {}".format(error.message)
            )
        detail.short.custom_variables = custom_variables['short']

    if custom_variables['long'] is not None:
        try:
            etree.fromstring("<variables>{}</variables>".format(custom_variables['long']))
        except etree.XMLSyntaxError as error:
            return HttpResponseBadRequest(
                "There was an issue with your custom variables: {}".format(error.message)
            )
        detail.long.custom_variables = custom_variables['long']

    if sort_elements is not None:
        detail.short.sort_elements = []
        for sort_element in sort_elements:
            item = SortElement()
            item.field = sort_element['field']
            item.type = sort_element['type']
            item.direction = sort_element['direction']
            item.display[lang] = sort_element['display']
            detail.short.sort_elements.append(item)
    if parent_select is not None:
        module.parent_select = ParentSelect.wrap(parent_select)
        if module_case_hierarchy_has_circular_reference(module):
            return HttpResponseBadRequest(_("The case hierarchy contains a circular reference."))
    if fixture_select is not None:
        module.fixture_select = FixtureSelect.wrap(fixture_select)
    if search_properties is not None:
        if search_properties.get('properties') is not None:
            module.search_config = CaseSearch(
                properties=[
                    CaseSearchProperty.wrap(p)
                    for p in _update_search_properties(
                        module,
                        search_properties.get('properties'), lang
                    )
                ],
                relevant=(
                    search_properties.get('relevant')
                    if search_properties.get('relevant') is not None
                    else CLAIM_DEFAULT_RELEVANT_CONDITION
                ),
                include_closed=bool(search_properties.get('include_closed')),
                default_properties=[
                    DefaultCaseSearchProperty.wrap(p)
                    for p in search_properties.get('default_properties')
                ]
            )

    resp = {}
    app.save(resp)
    return json_response(resp)
Beispiel #8
0
def edit_module_attr(request, domain, app_id, module_id, attr):
    """
    Called to edit any (supported) module attribute, given by attr
    """
    attributes = {
        "all": None,
        "auto_select_case": None,
        "case_label": 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_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,
        "referral_label": None,
        "root_module_id": None,
        "source_module_id": None,
        "task_list": ('task_list-show', 'task_list-label'),
        "excl_form_ids": None,
        "display_style": 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)
    module = app.get_module(module_id)
    lang = request.COOKIES.get('lang', app.langs[0])
    resp = {'update': {}, 'corrections': {}}
    if should_edit("case_type"):
        case_type = request.POST.get("case_type", None)
        if not case_type or is_valid_case_type(case_type, module):
            old_case_type = module["case_type"]
            module["case_type"] = case_type
            for cp_mod in (mod for mod in app.modules if isinstance(mod, CareplanModule)):
                if cp_mod.unique_id != module.unique_id and cp_mod.parent_select.module_id == module.unique_id:
                    cp_mod.case_type = case_type

            def rename_action_case_type(mod):
                for form in mod.forms:
                    for action in form.actions.get_all_actions():
                        if action.case_type == old_case_type:
                            action.case_type = case_type

            if isinstance(module, AdvancedModule):
                rename_action_case_type(module)
            for ad_mod in (mod for mod in app.modules if isinstance(mod, AdvancedModule)):
                if ad_mod.unique_id != module.unique_id and ad_mod.case_type != old_case_type:
                    # only apply change if the module's case_type does not reference the old value
                    rename_action_case_type(ad_mod)
        elif case_type == USERCASE_TYPE and not isinstance(module, AdvancedModule):
            return HttpResponseBadRequest('"{}" is a reserved case type'.format(USERCASE_TYPE))
        else:
            return HttpResponseBadRequest("case type is improperly formatted")
    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_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)

    for attribute in ("name", "case_label", "referral_label"):
        if should_edit(attribute):
            name = request.POST.get(attribute, None)
            module[attribute][lang] = name
            if should_edit("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"):
        if not request.POST.get("root_module_id"):
            module["root_module_id"] = None
        else:
            try:
                app.get_module(module_id)
                module["root_module_id"] = request.POST.get("root_module_id")
            except ModuleNotFoundException:
                messages.error(_("Unknown Menu"))

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