# HG changeset patch # User Goffi # Date 1614447398 -3600 # Node ID e12e9e1535d37399fbc08573bbc4d228d3a70c5e # Parent d897597cfa94bf9cd9ea64b8f38aaea381c3daf6 tools (xml_tools): new `dataForm2dataDict` and `dataDict2dataForm`: those methods convert a serialisable dict format to `wokkel.data_form.Form` and vice versa diff -r d897597cfa94 -r e12e9e1535d3 sat/plugins/plugin_misc_lists.py --- a/sat/plugins/plugin_misc_lists.py Sat Feb 27 18:33:53 2021 +0100 +++ b/sat/plugins/plugin_misc_lists.py Sat Feb 27 18:36:38 2021 +0100 @@ -20,10 +20,10 @@ from twisted.internet import defer from twisted.words.xish import domish from twisted.words.protocols.jabber import jid -from wokkel import data_form from sat.core.i18n import _, D_ from sat.core.xmpp import SatXMPPEntity from sat.core.constants import Const as C +from sat.tools import xml_tools from sat.tools.common import uri from sat.tools.common import data_format from sat.core.log import getLogger @@ -455,38 +455,13 @@ name = name.strip() if not name: name = shortuuid.uuid() - template = TEMPLATES[template_id] - - fields = [ - data_form.Field(fieldType="hidden", var=NS_TICKETS_TYPE, value=template_id) - ] - for field_data in template['fields']: - field_type = field_data.get('type', 'text-single') - kwargs = { - "fieldType": field_type, - "var": field_data["name"], - "label": field_data.get('label'), - "value": field_data.get("value"), - } - if field_type == "xhtml": - kwargs.update({ - "fieldType": None, - "ext_type": "xml", - }) - if kwargs["value"] is None: - kwargs["value"] = domish.Element((C.NS_XHTML, "div")) - elif "options" in field_data: - kwargs["options"] = [ - data_form.Option(o["value"], o.get("label")) - for o in field_data["options"] - ] - field = data_form.Field(**kwargs) - fields.append(field) - - schema = data_form.Form( - "form", - formNamespace=APP_NS_TICKETS, - fields=fields + fields = TEMPLATES[template_id]["fields"].copy() + fields.insert( + 0, + {"type": "hidden", "name": NS_TICKETS_TYPE, "value": template_id} + ) + schema = xml_tools.dataDict2dataForm( + {"namespace": APP_NS_TICKETS, "fields": fields} ).toElement() service = client.jid.userhostJID() diff -r d897597cfa94 -r e12e9e1535d3 sat/tools/xml_tools.py --- a/sat/tools/xml_tools.py Sat Feb 27 18:33:53 2021 +0100 +++ b/sat/tools/xml_tools.py Sat Feb 27 18:36:38 2021 +0100 @@ -194,6 +194,92 @@ return dataForm2Widgets(form_ui, form, read_only=read_only) +def dataForm2dataDict(form: data_form.Form) -> dict: + """Convert data form to a simple dict, easily serialisable + + see dataDict2dataForm for a description of the format + """ + fields = [] + data_dict = { + "fields": fields + } + if form.formNamespace: + data_dict["namespace"] = form.formNamespace + for form_field in form.fieldList: + field = {"type": form_field.fieldType} + fields.append(field) + for src_name, dest_name in ( + ('var', 'name'), + ('label', 'label'), + ('value', 'value'), + ): + value = getattr(form_field, src_name, None) + if value: + field[dest_name] = value + if form_field.options: + options = field["options"] = [] + for form_opt in form_field.options: + opt = {"value": form_opt.value} + if form_opt.label: + opt["label"] = form_opt.label + options.append(opt) + + if form_field.fieldType is None and form_field.ext_type == "xml": + if isinstance(form_field.value, domish.Element): + if ((form_field.value.uri == C.NS_XHTML + and form_field.value.name == "div")): + field["type"] = "xhtml" + if form_field.value.children: + log.warning( + "children are not managed for XHTML fields: " + f"{form_field.value.toXml()}" + ) + return data_dict + + +def dataDict2dataForm(data_dict): + """Convert serialisable dict of data to a data form + + The format of the dict is as follow: + - an optional "namespace" key with form namespace + - a mandatory "fields" key with list of fields as follow: + - "type" is mostly the same as data_form.Field.fieldType + - "var", "label", and "value" follow same attribude in data_form.Field + - "xhtml" is used for "xml" fields with child in the C.NS_XHTML namespace + - "options" are list of dict with optional "label" and mandatory "value" + following suitable attributes from data_form.Option + """ + # TODO: describe format + fields = [] + for field_data in data_dict["fields"]: + field_type = field_data.get('type', 'text-single') + kwargs = { + "fieldType": field_type, + "var": field_data["name"], + "label": field_data.get('label'), + "value": field_data.get("value"), + } + if field_type == "xhtml": + kwargs.update({ + "fieldType": None, + "ext_type": "xml", + }) + if kwargs["value"] is None: + kwargs["value"] = domish.Element((C.NS_XHTML, "div")) + elif "options" in field_data: + kwargs["options"] = [ + data_form.Option(o["value"], o.get("label")) + for o in field_data["options"] + ] + field = data_form.Field(**kwargs) + fields.append(field) + return data_form.Form( + "form", + formNamespace=data_dict.get("namespace"), + fields=fields + ) + + def dataFormEltResult2XMLUIData(form_xml): """Parse a data form result (not parsed by Wokkel's XEP-0004 implementation).