Skip to content

Commit

Permalink
Merge pull request #34809 from dimagi/ml/case-tile-translations
Browse files Browse the repository at this point in the history
Support translatable words within calculated properties in case tiles
  • Loading branch information
minhaminha authored Aug 8, 2024
2 parents 9dec85e + 64d0085 commit e97b0e1
Show file tree
Hide file tree
Showing 21 changed files with 278 additions and 29 deletions.
2 changes: 1 addition & 1 deletion corehq/apps/app_manager/app_strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
35 changes: 30 additions & 5 deletions corehq/apps/app_manager/detail_screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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%"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
'use strict';
/**
* Model for a column in the Display Properties section of case list/detail.
*
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}());
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
'use strict';
/* globals DOMPurify */
/**
* Contains a few UI utilities for the Display Properties
Expand Down Expand Up @@ -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({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
<locale id="{title_text_id}"/>
</text>
</title>

<variables>
{custom_variables}
</variables>
<field>
<style horz-align="left" vert-align="center" font-size="small">
<grid grid-height="1" grid-width="12" grid-x="0" grid-y="0"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
<locale id="{title_text_id}"/>
</text>
</title>

<variables>
{custom_variables}
</variables>
<field>
<style horz-align="center" vert-align="top" font-size="small">
<grid grid-height="1" grid-width="1" grid-x="0" grid-y="0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
<locale id="{title_text_id}"/>
</text>
</title>

<variables>
{custom_variables}
</variables>
<field>
<style horz-align="left" vert-align="center" font-size="small" show-border="true">
<grid grid-height="1" grid-width="12" grid-x="0" grid-y="0"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
<locale id="{title_text_id}"/>
</text>
</title>

<variables>
{custom_variables}
</variables>
<field>
<style
horz-align="left"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
<locale id="{title_text_id}"/>
</text>
</title>

<variables>
{custom_variables}
</variables>
<field>
<style horz-align="left" vert-align="center" font-size="medium">
<grid grid-height="1" grid-width="12" grid-x="0" grid-y="0"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
<locale id="{title_text_id}"/>
</text>
</title>

<variables>
{custom_variables}
</variables>
<field>
<style horz-align="left" vert-align="center" font-size="small">
<grid grid-height="1" grid-width="12" grid-x="0" grid-y="0"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
<locale id="{title_text_id}"/>
</text>
</title>

<variables>
{custom_variables}
</variables>
<field>
<style
horz-align="center"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
<locale id="{title_text_id}"/>
</text>
</title>

<variables>
{custom_variables}
</variables>
<action>
<display>
<text>
Expand Down
27 changes: 22 additions & 5 deletions corehq/apps/app_manager/suite_xml/features/case_tiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from corehq.apps.app_manager import id_strings
from corehq.apps.app_manager.exceptions import SuiteError
from corehq.apps.app_manager.suite_xml.xml_models import (
Detail, XPathVariable, TileGroup, Style, EndpointAction
Detail, DetailVariable, XPathVariable, TileGroup, Style, EndpointAction
)

TILE_DIR = Path(__file__).parent.parent / "case_tile_templates"
Expand Down Expand Up @@ -113,6 +113,7 @@ def build_case_tile_detail(self, detail, start, end):
for template_field in case_tile_template_config(self.detail.case_tile_template).fields:
column = self._get_matched_detail_column(template_field)
context[template_field] = self._get_column_context(column)
context['custom_variables'] = self._get_custom_variables(self.detail.custom_variables_dict)

# Populate the template
detail_as_string = self._case_tile_template_string.format(**context)
Expand Down Expand Up @@ -181,14 +182,14 @@ def _get_column_context(self, column):
"prefix": escape(
column.header.get(default_lang, "")
),
"format": column.format
"format": column.format,
"variables": '',
"endpoint_action": '',
}

context['variables'] = ''
if column.format in ["enum", "conditional-enum", "enum-image", "clickable-icon"]:
if column.format in ["enum", "conditional-enum", "enum-image", "clickable-icon", "translatable-enum"]:
context["variables"] = self._get_enum_variables(column)

context['endpoint_action'] = ''
if column.endpoint_action_id:
context["endpoint_action"] = self._get_endpoint_action(column.endpoint_action_id)
return context
Expand All @@ -200,6 +201,10 @@ def _get_xpath_function(self, column):
else:
xpath_function = self._escape_xpath_function(get_column_generator(
self.app, self.module, self.detail, column).xpath_function)
if column.format == "translatable-enum":
for enum in column.enum:
if enum.key in xpath_function and 'k' + enum.key not in xpath_function:
xpath_function = xpath_function.replace(enum.key, 'k' + enum.key)
return xpath_function

@staticmethod
Expand Down Expand Up @@ -274,3 +279,15 @@ def _compare_fields_by_order(initial_field, incoming_field):
elif initial_field.sort_node.order is None:
return incoming_field
return min(initial_field, incoming_field, key=lambda field: field.sort_node.order)

@staticmethod
def _get_custom_variables(custom_var_dict):
variables = []
for var_name, var_function in custom_var_dict.items():
variables.append(
DetailVariable(
name=var_name,
function=var_function
).serialize()
)
return ''.join([bytes(variable).decode('utf-8') for variable in variables])
17 changes: 13 additions & 4 deletions corehq/apps/app_manager/suite_xml/xml_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,23 @@ def build(cls, enum, format, type, template, get_template_context, get_value):
v_val = get_value(v_key)
variables.append(XPathVariable(name=v_key, locale_id=v_val))
parts = []
for i, item in enumerate(enum):
template_context = get_template_context(item, i)
parts.append(template.format(**template_context))
if format == 'translatable-enum':
calculated_property = get_template_context()['calculated_property']
# converting variables into suite.xml recognized variables (i.e. $variable > $kvariable)
for item in enum:
key = item.key_as_variable
if key[1:] in calculated_property:
calculated_property = calculated_property.replace(key[1:], key)
parts.append(calculated_property)
else:
for i, item in enumerate(enum):
template_context = get_template_context(item, i)
parts.append(template.format(**template_context))
if type == "display" and format == "enum":
parts.insert(0, "replace(join(' ', ")
parts[-1] = parts[-1][:-2] # removes extra comma from last string
parts.append("), '\\s+', ' ')")
else:
elif format != "translatable-enum":
parts.append("''")
parts.append(")" * len(enum))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@
<locale id="cchq.case"/>
</text>
</title>
<variables>

</variables>
<action>
<display>
<text>
Expand Down
3 changes: 3 additions & 0 deletions corehq/apps/app_manager/tests/data/suite/suite-case-tiles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
<locale id="cchq.case"/>
</text>
</title>
<variables>

</variables>
<action>
<display>
<text>
Expand Down
Loading

0 comments on commit e97b0e1

Please sign in to comment.