misc: use status colours in ods export (#8231) #858

Merged
fpeters merged 1 commits from wip/8231-ods-status-colour into main 2023-11-24 09:13:04 +01:00
5 changed files with 86 additions and 6 deletions

View File

@ -861,6 +861,8 @@ def test_backoffice_ods(pub):
with zipfile.ZipFile(io.BytesIO(resp.body)) as zipf:
with zipf.open('content.xml') as fd:
ods_sheet = ET.parse(fd)
with zipf.open('styles.xml') as fd:
styles_sheet = ET.parse(fd)
# check the ods contains a link to the document
elem = ods_sheet.findall('.//{%s}a' % ods.NS['text'])[0]
assert (
@ -883,6 +885,7 @@ def test_backoffice_ods(pub):
not_number_column = all_texts.index('not a number, with underscore')
zero_number_column = all_texts.index('number field with zero')
numeric_column = all_texts.index('real numeric field')
status_column = all_texts.index('Status')
for row in ods_sheet.findall('.//{%s}table-row' % ods.NS['table']):
if (
@ -981,6 +984,21 @@ def test_backoffice_ods(pub):
]
== '234.56'
)
assert (
row.findall('.//{%s}table-cell' % ods.NS['table'])[status_column].attrib[
'{%s}style-name' % ods.NS['table']
]
== 'StatusStyle-new'
)
status_style = [
x
for x in styles_sheet.findall('.//{%s}style' % ods.NS['style'])
if x.attrib['{%s}name' % ods.NS['style']] == 'StatusStyle-new'
][0]
cell_props = status_style.find('{%s}table-cell-properties' % ods.NS['style'])
text_props = status_style.find('{%s}text-properties' % ods.NS['style'])
assert cell_props.attrib['{%s}background-color' % ods.NS['fo']] == '#66FF00'
assert text_props.attrib['{%s}color' % ods.NS['fo']] == '#000000'
def test_backoffice_empty_ods(pub):

View File

@ -121,7 +121,8 @@ def geojson_formdatas(formdatas, geoloc_key='base', fields=None):
if field.key in ('map', 'computed'):
continue
html_value = formdata.get_field_view_value(field, max_length=60)
html_value = html_value.replace('[download]', '%sdownload' % formdata_backoffice_url)
if hasattr(html_value, 'replace'):
html_value = html_value.replace('[download]', '%sdownload' % formdata_backoffice_url)
value = formdata.get_field_view_value(field)
if not html_value and not value:
continue

View File

@ -918,7 +918,31 @@ class FormData(StorableObject):
if field.key == 'user-label':
return self.get_user_label() or '-'
if field.key == 'status':
return self.get_status_label()
class StatusFieldValue:
def __init__(self, status):
self.status = status
def get_ods_style_name(self):
return 'StatusStyle-%s' % misc.simplify(self.status.name) if self.status else None
def get_ods_colour(self, colour):
return {'black': '#000000', 'white': '#ffffff'}.get(colour, colour)
def get_ods_style_bg_colour(self):
return self.get_ods_colour(self.status.colour) if self.status else 'transparent'
def get_ods_style_fg_colour(self):
return (
self.get_ods_colour(self.status.get_contrast_color())
if self.status
else '#000000'
)
def __str__(self):
return get_publisher().translate(self.status.name) if self.status else _('Unknown')
return StatusFieldValue(self.get_status())
if field.key == 'submission_channel':
return self.get_submission_channel_label()
if field.key == 'submission_agent':

View File

@ -338,7 +338,9 @@ class FormDefUI:
r += htmltext('<td class="%s">' % css_class)
else:
r += htmltext('<td>')
r += field_value.replace('[download]', str('%sdownload' % link))
if hasattr(field_value, 'replace'):
field_value = field_value.replace('[download]', str('%sdownload' % link))
r += field_value
r += htmltext('</td>')
r += htmltext('</tr>\n')
return r.getvalue()

View File

@ -146,6 +146,22 @@ class Workbook:
define_date_style('Date', date_format())
define_date_style('DateTime', datetime_format())
for sheet in self.sheets:
for extra_style_name, extra_style_props in sheet.extra_styles.items():
if not extra_style_props:
continue
node = ET.SubElement(automatic_styles, '{%s}style' % NS['style'])
node.attrib['{%s}name' % NS['style']] = extra_style_name
node.attrib['{%s}family' % NS['style']] = 'table-cell'
cell_props = ET.SubElement(node, '{%s}table-cell-properties' % NS['style'])
if 'background-color' in extra_style_props:
cell_props.attrib['{%s}background-color' % NS['fo']] = extra_style_props.get(
'background-color'
)
text_props = ET.SubElement(node, '{%s}text-properties' % NS['style'])
if 'color' in extra_style_props:
text_props.attrib['{%s}color' % NS['fo']] = extra_style_props.get('color')
return root
def get_styles(self):
@ -177,6 +193,7 @@ class WorkSheet:
self.cells = {}
self.name = name
self.workbook = workbook
self.extra_styles = {}
def write(self, row, column, value, **kwargs):
if row not in self.cells:
@ -201,7 +218,12 @@ class WorkSheet:
if not cell:
ET.SubElement(row, '{%s}table-cell' % NS['table'])
else:
row.append(cell.get_node())
cell_node = cell.get_node()
style_name = cell.get_style_name()
if style_name:
cell_node.attrib['{%s}style-name' % NS['table']] = style_name
self.extra_styles[style_name] = cell.get_style_properties()
row.append(cell_node)
return root
@ -237,14 +259,12 @@ class WorkCell:
a.text = self.native_value
p.text = None
elif self.data_field.key in ('time', 'last_update_time'):
root.attrib['{%s}style-name' % NS['table']] = 'DateTime'
root.attrib['{%s}value-type' % NS['office']] = 'date'
root.attrib['{%s}date-value' % NS['office']] = strftime(
'%Y-%m-%dT%H:%M:%S', make_datetime(self.native_value)
)
p.text = strftime(datetime_format(), make_datetime(self.native_value))
elif self.data_field.key == 'date':
root.attrib['{%s}style-name' % NS['table']] = 'Date'
root.attrib['{%s}value-type' % NS['office']] = 'date'
root.attrib['{%s}date-value' % NS['office']] = strftime('%Y-%m-%d', make_date(self.native_value))
p.text = strftime(date_format(), make_datetime(self.native_value))
@ -253,3 +273,18 @@ class WorkCell:
root.attrib['{%s}value' % NS['office']] = get_as_string_number(self.value)
return root
def get_style_name(self):
if self.data_field and self.data_field.key in ('time', 'last_update_time'):
return 'DateTime'
elif self.data_field and self.data_field.key == 'date':
return 'Date'
elif hasattr(self.native_value, 'get_ods_style_name'):
return self.native_value.get_ods_style_name()
def get_style_properties(self):
if hasattr(self.native_value, 'get_ods_style_name'):
return {
'background-color': self.native_value.get_ods_style_bg_colour(),
'color': self.native_value.get_ods_style_fg_colour(),
}