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
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)
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))
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)
def edit_module_attr(request, domain, app_id, module_unique_id, attr): """ Called to edit any (supported) module attribute, given by attr """ attributes = { "all": None, "auto_select_case": None, "case_list": ('case_list-show', 'case_list-label'), "case_list-menu_item_media_audio": None, "case_list-menu_item_media_image": None, 'case_list-menu_item_use_default_image_for_all': None, 'case_list-menu_item_use_default_audio_for_all': None, "case_list_form_id": None, "case_list_form_label": None, "case_list_form_media_audio": None, "case_list_form_media_image": None, 'case_list_form_use_default_image_for_all': None, 'case_list_form_use_default_audio_for_all': None, "case_list_post_form_workflow": None, "case_type": None, 'comment': None, "display_separately": None, "has_schedule": None, "media_audio": None, "media_image": None, "module_filter": None, "name": None, "name_enum": None, "parent_module": None, "put_in_root": None, "root_module_id": None, "source_module_id": None, "task_list": ('task_list-show', 'task_list-label'), "excl_form_ids": None, "display_style": None, "custom_icon_form": None, "custom_icon_text_body": None, "custom_icon_xpath": None, "use_default_image_for_all": None, "use_default_audio_for_all": None, } if attr not in attributes: return HttpResponseBadRequest() def should_edit(attribute): if attribute == attr: return True if 'all' == attr: if attributes[attribute]: for param in attributes[attribute]: if not request.POST.get(param): return False return True else: return request.POST.get(attribute) is not None app = get_app(domain, app_id) try: module = app.get_module_by_unique_id(module_unique_id) except ModuleNotFoundException: # temporary fallback module = app.get_module(module_unique_id) lang = request.COOKIES.get('lang', app.langs[0]) resp = {'update': {}, 'corrections': {}} if should_edit("custom_icon_form"): error_message = handle_custom_icon_edits(request, module, lang) if error_message: return json_response( {'message': error_message}, status_code=400 ) if should_edit("name_enum"): name_enum = json.loads(request.POST.get("name_enum")) module.name_enum = [MappingItem(i) for i in name_enum] if should_edit("case_type"): case_type = request.POST.get("case_type", None) if case_type == USERCASE_TYPE and not isinstance(module, AdvancedModule): return HttpResponseBadRequest('"{}" is a reserved case type'.format(USERCASE_TYPE)) elif case_type and not is_valid_case_type(case_type, module): return HttpResponseBadRequest("case type is improperly formatted") else: old_case_type = module["case_type"] module["case_type"] = case_type # rename other reference to the old case type all_advanced_modules = [] modules_with_old_case_type_exist = False for mod in app.modules: if isinstance(mod, AdvancedModule): all_advanced_modules.append(mod) modules_with_old_case_type_exist |= mod.case_type == old_case_type for mod in all_advanced_modules: for form in mod.forms: for action in form.actions.get_load_update_actions(): if action.case_type == old_case_type and action.details_module == module_unique_id: action.case_type = case_type if mod.unique_id == module_unique_id or not modules_with_old_case_type_exist: for action in form.actions.get_open_actions(): if action.case_type == old_case_type: action.case_type = case_type if should_edit("put_in_root"): module["put_in_root"] = json.loads(request.POST.get("put_in_root")) if should_edit("display_style"): module["display_style"] = request.POST.get("display_style") if should_edit("source_module_id"): module["source_module_id"] = request.POST.get("source_module_id") if should_edit("display_separately"): module["display_separately"] = json.loads(request.POST.get("display_separately")) if should_edit("parent_module"): parent_module = request.POST.get("parent_module") module.parent_select.module_id = parent_module if module_case_hierarchy_has_circular_reference(module): return HttpResponseBadRequest(_("The case hierarchy contains a circular reference.")) if should_edit("auto_select_case"): module["auto_select_case"] = request.POST.get("auto_select_case") == 'true' if app.enable_module_filtering and should_edit('module_filter'): module['module_filter'] = request.POST.get('module_filter') if should_edit('case_list_form_id'): module.case_list_form.form_id = request.POST.get('case_list_form_id') if should_edit('case_list_form_label'): module.case_list_form.label[lang] = request.POST.get('case_list_form_label') if should_edit('case_list_post_form_workflow'): module.case_list_form.post_form_workflow = request.POST.get('case_list_post_form_workflow') if should_edit("name"): name = request.POST.get("name", None) module["name"][lang] = name resp['update'] = {'.variable-module_name': trans(module.name, [lang], use_delim=False)} if should_edit('comment'): module.comment = request.POST.get('comment') for SLUG in ('case_list', 'task_list'): show = '{SLUG}-show'.format(SLUG=SLUG) label = '{SLUG}-label'.format(SLUG=SLUG) if request.POST.get(show) == 'true' and (request.POST.get(label) == ''): # Show item, but empty label, was just getting ignored return HttpResponseBadRequest("A label is required for {SLUG}".format(SLUG=SLUG)) if should_edit(SLUG): module[SLUG].show = json.loads(request.POST[show]) module[SLUG].label[lang] = request.POST[label] if should_edit("root_module_id"): old_root = module['root_module_id'] if not request.POST.get("root_module_id"): module["root_module_id"] = None else: module["root_module_id"] = request.POST.get("root_module_id") if not old_root and module['root_module_id']: track_workflow(request.couch_user.username, "User associated module with a parent") elif old_root and not module['root_module_id']: track_workflow(request.couch_user.username, "User orphaned a child module") if should_edit('excl_form_ids') and isinstance(module, ShadowModule): excl = request.POST.getlist('excl_form_ids') excl.remove('0') # Placeholder value to make sure excl_form_ids is POSTed when no forms are excluded module.excluded_form_ids = excl handle_media_edits(request, module, should_edit, resp, lang) handle_media_edits(request, module.case_list_form, should_edit, resp, lang, prefix='case_list_form_') handle_media_edits(request, module.case_list, should_edit, resp, lang, prefix='case_list-menu_item_') app.save(resp) resp['case_list-show'] = module.requires_case_details() return HttpResponse(json.dumps(resp))
def edit_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)
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))