tools (xml_tools): new dataForm2dataDict and dataDict2dataForm:

those methods convert a serialisable dict format to `wokkel.data_form.Form` and vice versa
This commit is contained in:
Goffi 2021-02-27 18:36:38 +01:00
commit 026ac9db13
2 changed files with 94 additions and 33 deletions

View file

@ -20,10 +20,10 @@ from typing import List, Tuple, Optional
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 @@ class PubsubLists:
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()

View file

@ -194,6 +194,92 @@ def dataForm2XMLUI(form, submit_id, session_id=None, read_only=False):
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).