示例#1
0
    def details(self):
        r = []
        from corehq.apps.app_manager.detail_screen import get_column_generator
        if not self.app.use_custom_suite:
            for module in self.modules:
                for detail in module.get_details():
                    detail_columns = detail.get_columns()

                    if detail_columns and detail.type in ('case_short', 'case_long'):
                        d = Detail(
                            id=self.id_strings.detail(module, detail),
                            title=Text(locale_id=self.id_strings.detail_title_locale(module, detail))
                        )

                        if detail.type == 'case_short':
                            detail_fields = [c.field for c in detail_columns]
                            sort_fields = [e.field for e in module.detail_sort_elements]
                            sort_only_fields = [field for field in sort_fields
                                                if field not in detail_fields]

                            from corehq.apps.app_manager.models import DetailColumn
                            for sort_field in sort_only_fields:
                                # set up a fake detailcolumn so we can
                                # add this field but not actually
                                # save it
                                dc = DetailColumn(
                                    model='case',
                                    field=sort_field,
                                    format='invisible',
                                )
                                detail.append_column(dc)

                            # need to add a default here so that it doesn't
                            # get persisted
                            if self.app.enable_multi_sort and \
                               len(module.detail_sort_elements) == 0:
                                from corehq.apps.app_manager.models import SortElement
                                try:
                                    se = SortElement()
                                    se.field = detail.columns[0].field
                                    se.type = 'string'
                                    se.direction = 'ascending'
                                    module.detail_sort_elements.append(se)
                                except Exception:
                                    pass

                        for column in detail.get_columns():
                            fields = get_column_generator(self.app, module, detail, column).fields
                            d.fields.extend(fields)

                        try:
                            if not self.app.enable_multi_sort:
                                d.fields[0].sort = 'default'
                        except IndexError:
                            pass
                        else:
                            # only yield the Detail if it has Fields
                            r.append(d)

        return r
示例#2
0
def get_default_sort_elements(detail):
    from corehq.apps.app_manager.models import SortElement

    if not detail.columns:
        return []

    def get_sort_params(column):
        if column.field_type == FIELD_TYPE_LEDGER:
            return dict(type='int', direction='descending')
        else:
            return dict(type='string', direction='ascending')

    col_0 = detail.get_column(0)
    sort_elements = [SortElement(
        field=col_0.field,
        **get_sort_params(col_0)
    )]

    for column in detail.columns[1:]:
        if column.field_type == FIELD_TYPE_LEDGER:
            sort_elements.append(SortElement(
                field=column.field,
                **get_sort_params(column)
            ))

    return sort_elements
示例#3
0
 def test_sort_calculation(self):
     app = Application.wrap(self.get_json('suite-advanced'))
     detail = app.modules[0].case_details.short
     detail.sort_elements.append(
         SortElement(
             field=detail.columns[0].field,
             type='string',
             direction='descending',
             blanks='first',
             sort_calculation='random()'
         )
     )
     sort_node = """
     <partial>
         <sort direction="descending" blanks="first" order="1" type="string">
           <text>
             <xpath function="random()"/>
           </text>
         </sort>
     </partial>
     """
     self.assertXmlPartialEqual(
         sort_node,
         app.create_suite(),
         "./detail[@id='m0_case_short']/field/sort"
     )
 def test_sort_cache_suite(self):
     app = Application.wrap(self.get_json('suite-advanced'))
     detail = app.modules[0].case_details.short
     detail.sort_elements.append(
         SortElement(
             field=detail.columns[0].field,
             type='index',
             direction='descending',
         ))
     self.assertXmlPartialEqual(self.get_xml('sort-cache'),
                                app.create_suite(),
                                "./detail[@id='m0_case_short']")
示例#5
0
def get_nodeset_sort_elements(detail):
    from corehq.apps.app_manager.models import SortElement
    sort_elements = []
    tab_spans = detail.get_tab_spans()
    for tab in detail.get_tabs():
        if tab.nodeset:
            tab_span = tab_spans[tab.id]
            for column in detail.columns[tab_span[0]:tab_span[1]]:
                if column.invisible:
                    sort_elements.append(
                        SortElement(field=column.field,
                                    type='string',
                                    direction='ascending'))
    return sort_elements
    def test_short_detail_xml_sort_only(self):
        short = self.case_details.short
        short.display = 'short'
        short.sort_elements.append(
            SortElement(
                field='gps',
                type='distance',
                direction='descending',
            )
        )

        suite = self.factory.app.create_suite()
        template_xpath = './detail[@id="m0_case_short"]/field'
        self.assertXmlHasXpath(suite, template_xpath)
        self.assertXmlPartialEqual(
            """
            <partial>
                <field>
                    <header>
                        <text>
                            <locale id="m0.case_short.case_name_1.header"/>
                        </text>
                    </header>
                    <template>
                        <text>
                            <xpath function="case_name"/>
                        </text>
                    </template>
                </field>
                <field>
                    <header width="0">
                        <text/>
                    </header>
                    <template width="0">
                        <text>
                            <xpath function="gps"/>
                        </text>
                    </template>
                    <sort direction="descending" order="1" type="double">
                        <text>
                            <xpath function="if(gps = '', 2147483647, round(distance(gps, here())))"/>
                        </text>
                    </sort>
                </field>
            </partial>
            """,
            suite,
            template_xpath
        )
示例#7
0
def get_detail_column_infos(detail, include_sort):
    """
    This is not intented to be a widely used format
    just a packaging of column info into a form most convenient for rendering
    """
    from corehq.apps.app_manager.models import SortElement

    DetailColumnInfo = namedtuple('DetailColumnInfo',
                                  'column sort_element order')
    if not include_sort:
        return [
            DetailColumnInfo(column, None, None)
            for column in detail.get_columns()
        ]

    if detail.sort_elements:
        sort_elements = detail.sort_elements
    elif detail.columns:
        sort_elements = [
            SortElement(
                field=detail.get_column(0).field,
                type='string',
                direction='ascending',
            )
        ]
    else:
        sort_elements = []

    # order is 1-indexed
    sort_elements = dict(
        (s.field, (s, i + 1)) for i, s in enumerate(sort_elements))
    columns = []
    for column in detail.get_columns():
        sort_element, order = sort_elements.pop(column.field, (None, None))
        columns.append(DetailColumnInfo(column, sort_element, order))

    # sort elements is now populated with only what's not in any column
    # add invisible columns for these
    sort_only = sorted(sort_elements.items(),
                       key=lambda (field, (sort_element, order)): order)

    for field, (sort_element, order) in sort_only:
        column = create_temp_sort_column(field, len(columns))
        columns.append(DetailColumnInfo(column, sort_element, order))
    return columns
示例#8
0
 def test_sort_cache_search(self):
     app = Application.wrap(self.get_json('suite-advanced'))
     app.modules[0].search_config = CaseSearch(
         properties=[CaseSearchProperty(name='name', label={'en': 'Name'})],
     )
     detail = app.modules[0].case_details.short
     detail.sort_elements.append(
         SortElement(
             field=detail.columns[0].field,
             type='index',
             direction='descending',
             blanks='first',
         )
     )
     self.assertXmlPartialEqual(
         self.get_xml('sort-cache-search'),
         app.create_suite(),
         "./detail[@id='m0_search_short']"
     )
示例#9
0
    def test_short_detail_xml_with_sort(self):
        short = self.case_details.short
        short.display = 'short'
        short_column = short.get_column(0)
        short.sort_elements.append(
            SortElement(
                field=short_column.field,
                type='distance',
                direction='descending',
            ))

        suite = self.factory.app.create_suite()
        template_xpath = './detail[@id="m0_case_short"]/field'
        self.assertXmlHasXpath(suite, template_xpath)
        self.assertXmlPartialEqual(
            """
            <partial>
                <field>
                    <header>
                        <text>
                            <locale id="m0.case_short.case_name_1.header"/>
                        </text>
                    </header>
                    <template>
                        <text>
                            <xpath function="case_name"/>
                        </text>
                    </template>
                    <sort direction="descending" order="1" type="double">
                        <text>
                            <xpath function="round(distance(case_name, here()))"/>
                        </text>
                    </sort>
                </field>
            </partial>
            """, suite, template_xpath)
示例#10
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)
    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)

    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)

    if short is not None:
        detail.short.columns = map(DetailColumn.wrap, short)
        if persist_case_context is not None:
            detail.short.persist_case_context = persist_case_context
        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)

    if long is not None:
        detail.long.columns = map(DetailColumn.wrap, 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 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']
            detail.short.sort_elements.append(item)
    if parent_select is not None:
        module.parent_select = ParentSelect.wrap(parent_select)
    if fixture_select is not None:
        module.fixture_select = FixtureSelect.wrap(fixture_select)

    resp = {}
    app.save(resp)
    return json_response(resp)
示例#11
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)
示例#12
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)
示例#13
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")

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

    resp = {}
    app.save(resp)
    return json_response(resp)
示例#14
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)