diff --git a/corehq/apps/app_manager/app_strings.py b/corehq/apps/app_manager/app_strings.py index 89fa5f8f18f6..b3c0b30179b1 100644 --- a/corehq/apps/app_manager/app_strings.py +++ b/corehq/apps/app_manager/app_strings.py @@ -155,7 +155,7 @@ def _create_module_details_app_strings(module, langs): clean_trans(column.header, langs) ) - if column.format in ('enum', 'conditional-enum', 'enum-image', 'clickable-icon'): + if column.format in ('enum', 'conditional-enum', 'enum-image', 'clickable-icon', 'translatable-enum'): for item in column.enum: yield ( id_strings.detail_column_enum_variable( diff --git a/corehq/apps/app_manager/detail_screen.py b/corehq/apps/app_manager/detail_screen.py index 7c418ad9eb33..669f19b9fd11 100644 --- a/corehq/apps/app_manager/detail_screen.py +++ b/corehq/apps/app_manager/detail_screen.py @@ -142,8 +142,7 @@ def template(self): form=self.template_form, width=self.template_width, ) - - if self.column.useXpathExpression: + if self.column.useXpathExpression and self.column.format != 'translatable-enum': xpath = sx.CalculatedPropertyXPath(function=self.xpath) if re.search(r'\$lang', self.xpath): xpath.variables.node.append( @@ -192,8 +191,9 @@ def sort_node(self): locale_id=self.id_strings.current_language() ).node ) - xpath_variable = sx.XPathVariable(name='calculated_property', xpath=xpath) - sort.text.xpath.variables.node.append(xpath_variable.node) + if self.column.format != 'translatable-enum': + xpath_variable = sx.XPathVariable(name='calculated_property', xpath=xpath) + sort.text.xpath.variables.node.append(xpath_variable.node) if self.sort_element: if not sort: @@ -307,7 +307,8 @@ def fields(self): endpoint_action=self.action, alt_text=self.alt_text, ) - elif self.sort_xpath_function and self.detail.display == 'short': + elif (self.sort_xpath_function and self.detail.display == 'short' + and self.column.format != 'translatable-enum'): yield sx.Field( style=self.style, header=self.header, @@ -517,6 +518,30 @@ def _xpath_template_context(self, type): } +@register_format_type('translatable-enum') +class TranslatableEnum(Enum): + @property + def sort_node(self): + node = super(TranslatableEnum, self).sort_node + if node: + variables = self.variables + for key in variables: + node.text.xpath.node.append( + sx.XPathVariable(name=key, locale_id=variables[key]).node + ) + return node + + def _make_xpath(self, type): + return sx.XPathEnum.build( + enum=self.column.enum, + format=self.column.format, + type=type, + template=None, + get_template_context=lambda: {'calculated_property': self.xpath}, + get_value=lambda key: self.id_strings.detail_column_enum_variable(self.module, self.detail_type, + self.column, key)) + + @register_format_type('late-flag') class LateFlag(HideShortHeaderColumn): template_width = "11%" diff --git a/corehq/apps/app_manager/static/app_manager/js/details/column.js b/corehq/apps/app_manager/static/app_manager/js/details/column.js index b0ce9092260b..166f83d166e0 100644 --- a/corehq/apps/app_manager/static/app_manager/js/details/column.js +++ b/corehq/apps/app_manager/static/app_manager/js/details/column.js @@ -1,3 +1,4 @@ +'use strict'; /** * Model for a column in the Display Properties section of case list/detail. * @@ -231,6 +232,9 @@ hqDefine("app_manager/js/details/column", function () { } } } + } else { + // Restrict Translatable Text usage to Calculated Properties only + menuOptions.splice(-1); } self.format = uiElement.select(menuOptions).val(self.original.format || null); @@ -245,6 +249,7 @@ hqDefine("app_manager/js/details/column", function () { multimedia: self.screen.config.multimedia, values_are_icons: self.original.format === 'enum-image', keys_are_conditions: self.original.format === 'conditional-enum', + values_are_translatable: self.original.format === 'translatable-enum', }; self.enum_extra = uiElement.key_value_mapping(o); }()); @@ -394,9 +399,11 @@ hqDefine("app_manager/js/details/column", function () { fireChange(); }); self.date_extra.value = format.val(); - } else if (this.val() === "enum" || this.val() === "enum-image" || this.val() === 'conditional-enum') { + } else if (this.val() === "enum" || this.val() === "enum-image" + || this.val() === 'conditional-enum' || this.val() === 'translatable-enum') { self.enum_extra.values_are_icons(this.val() === 'enum-image'); self.enum_extra.keys_are_conditions(this.val() === 'conditional-enum'); + self.enum_extra.values_are_translatable(this.val() === 'translatable-enum'); self.format.ui.parent().append(self.enum_extra.ui); } else if (this.val() === "clickable-icon") { self.enum_extra.values_are_icons(true); diff --git a/corehq/apps/app_manager/static/app_manager/js/details/utils.js b/corehq/apps/app_manager/static/app_manager/js/details/utils.js index f79db7b6e21a..73ee985c0a7b 100644 --- a/corehq/apps/app_manager/static/app_manager/js/details/utils.js +++ b/corehq/apps/app_manager/static/app_manager/js/details/utils.js @@ -1,3 +1,4 @@ +'use strict'; /* globals DOMPurify */ /** * Contains a few UI utilities for the Display Properties @@ -80,6 +81,12 @@ hqDefine("app_manager/js/details/utils", function () { label: gettext('Conditional ID Mapping'), }); } + if (addOns.calc_xpaths) { + formats.push({ + value: "translatable-enum", + label: gettext('Translatable Text'), + }); + } if (hqImport('hqwebapp/js/toggles').toggleEnabled('VELLUM_CASE_MICRO_IMAGE')) { formats.push({ diff --git a/corehq/apps/app_manager/suite_xml/case_tile_templates/bha_referrals.xml b/corehq/apps/app_manager/suite_xml/case_tile_templates/bha_referrals.xml index 9abd4cae34d0..ca84f4ec0792 100644 --- a/corehq/apps/app_manager/suite_xml/case_tile_templates/bha_referrals.xml +++ b/corehq/apps/app_manager/suite_xml/case_tile_templates/bha_referrals.xml @@ -4,7 +4,9 @@ - + + {custom_variables} +