general: add support for cards as data source (#35089)
This commit is contained in:
parent
f7f14c0095
commit
73da9459bd
|
@ -1248,7 +1248,7 @@ def test_form_edit_field_advanced(pub):
|
|||
resp.body.index('<label for="form_data_source">Data Source</label>')
|
||||
|
||||
# start filling the "data source" field
|
||||
resp.forms[0]['data_source$type'] = 'JSON URL'
|
||||
resp.forms[0]['data_source$type'] = 'json'
|
||||
resp.forms[0]['data_source$value'] = 'http://example.net'
|
||||
resp = resp.forms[0].submit('submit')
|
||||
resp = resp.follow()
|
||||
|
@ -1379,6 +1379,72 @@ def test_form_edit_item_field(pub):
|
|||
assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1'
|
||||
assert FormDef.get(1).fields[0].items == ['XXX']
|
||||
|
||||
def test_form_edit_item_field_data_source(pub):
|
||||
create_superuser(pub)
|
||||
create_role()
|
||||
|
||||
FormDef.wipe()
|
||||
formdef = FormDef()
|
||||
formdef.name = 'form title'
|
||||
formdef.fields = [fields.ItemField(id='1', label='1st field', type='item')]
|
||||
formdef.store()
|
||||
|
||||
app = login(get_app(pub))
|
||||
resp = app.get('/backoffice/forms/1/fields/1/')
|
||||
assert resp.form['data_source$type'].options == [
|
||||
(u'None', True, u'None'),
|
||||
(u'json', False, u'JSON URL'),
|
||||
(u'jsonp', False, u'JSONP URL'),
|
||||
(u'python', False, u'Python Expression')
|
||||
]
|
||||
resp = resp.form.submit('submit').follow()
|
||||
|
||||
data_source = NamedDataSource(name='Foobar')
|
||||
data_source.data_source = {'type': 'formula', 'value': '[]'}
|
||||
data_source.store()
|
||||
|
||||
resp = app.get('/backoffice/forms/1/fields/1/')
|
||||
assert resp.form['data_source$type'].options == [
|
||||
(u'None', True, u'None'),
|
||||
(u'foobar', False, u'Foobar'),
|
||||
(u'json', False, u'JSON URL'),
|
||||
(u'jsonp', False, u'JSONP URL'),
|
||||
(u'python', False, u'Python Expression')
|
||||
]
|
||||
resp.form['data_source$type'].value = 'foobar'
|
||||
resp = resp.form.submit('submit').follow()
|
||||
assert FormDef.get(formdef.id).fields[0].data_source == {'type': 'foobar'}
|
||||
|
||||
carddef = CardDef()
|
||||
carddef.name = 'Baz'
|
||||
carddef.store()
|
||||
|
||||
resp = app.get('/backoffice/forms/1/fields/1/')
|
||||
assert resp.form['data_source$type'].options == [
|
||||
(u'None', False, u'None'),
|
||||
(u'foobar', True, u'Foobar'),
|
||||
(u'json', False, u'JSON URL'),
|
||||
(u'jsonp', False, u'JSONP URL'),
|
||||
(u'python', False, u'Python Expression')
|
||||
]
|
||||
|
||||
carddef.digest_template = 'plop'
|
||||
carddef.store()
|
||||
|
||||
resp = app.get('/backoffice/forms/1/fields/1/')
|
||||
assert resp.form['data_source$type'].options == [
|
||||
(u'None', False, u'None'),
|
||||
(u'carddef:%s' % carddef.url_name, False, u'Baz'),
|
||||
(u'foobar', True, u'Foobar'),
|
||||
(u'json', False, u'JSON URL'),
|
||||
(u'jsonp', False, u'JSONP URL'),
|
||||
(u'python', False, u'Python Expression')
|
||||
]
|
||||
|
||||
resp.form['data_source$type'].value = 'carddef:%s' % carddef.url_name
|
||||
resp = resp.form.submit('submit').follow()
|
||||
assert FormDef.get(formdef.id).fields[0].data_source == {'type': 'carddef:%s' % carddef.url_name}
|
||||
|
||||
def test_form_edit_items_field(pub):
|
||||
create_superuser(pub)
|
||||
create_role()
|
||||
|
@ -4584,7 +4650,7 @@ def test_data_sources_new(pub):
|
|||
resp = resp.click('New Data Source')
|
||||
resp.forms[0]['name'] = 'a new data source'
|
||||
resp.forms[0]['description'] = 'description of the data source'
|
||||
resp.forms[0]['data_source$type'] = 'Python Expression'
|
||||
resp.forms[0]['data_source$type'] = 'python'
|
||||
resp = resp.forms[0].submit('data_source$apply')
|
||||
resp.forms[0]['data_source$value'] = repr(
|
||||
[{'id': '1', 'text': 'un'}, {'id': '2', 'text': 'deux'}])
|
||||
|
@ -4605,7 +4671,7 @@ def test_data_sources_new(pub):
|
|||
resp = resp.click('New Data Source')
|
||||
resp.forms[0]['name'] = 'an other data source'
|
||||
resp.forms[0]['description'] = 'description of the data source'
|
||||
resp.forms[0]['data_source$type'] = 'Python Expression'
|
||||
resp.forms[0]['data_source$type'] = 'python'
|
||||
resp = resp.forms[0].submit('data_source$apply')
|
||||
resp.forms[0]['data_source$value'] = repr(
|
||||
[{'id': '1', 'text': 'un'}, {'id': '2', 'text': 'deux'}])
|
||||
|
|
|
@ -23,6 +23,7 @@ from quixote.http_request import Upload as QuixoteUpload
|
|||
from wcs.qommon.emails import docutils
|
||||
from wcs.qommon.form import UploadedFile
|
||||
from wcs.qommon.ident.password_accounts import PasswordAccount
|
||||
from wcs.carddef import CardDef
|
||||
from wcs.formdef import FormDef
|
||||
from wcs.workflows import (Workflow, EditableWorkflowStatusItem,
|
||||
DisplayMessageWorkflowStatusItem, WorkflowBackofficeFieldsFormDef,
|
||||
|
@ -4886,6 +4887,46 @@ def test_form_page_profile_verified_radio_item_prefill(pub):
|
|||
assert 'Check values then click submit.' in resp.body
|
||||
assert resp.form['f0'].value == 'foo@localhost' # it is reverted
|
||||
|
||||
def test_item_field_from_cards(pub):
|
||||
user = create_user(pub)
|
||||
formdef = create_formdef()
|
||||
formdef.data_class().wipe()
|
||||
|
||||
carddef = CardDef()
|
||||
carddef.name = 'items'
|
||||
carddef.digest_template = '{{form_var_name}}'
|
||||
carddef.fields = [
|
||||
fields.StringField(id='0', label='string', varname='name'),
|
||||
fields.StringField(id='1', label='string', varname='attr'),
|
||||
]
|
||||
carddef.store()
|
||||
for i, value in enumerate(['foo', 'bar', 'baz']):
|
||||
carddata = carddef.data_class()()
|
||||
carddata.data = {
|
||||
'0': value,
|
||||
'1': 'attr%s' % i,
|
||||
}
|
||||
carddata.just_created()
|
||||
carddata.store()
|
||||
|
||||
ds = {'type': 'carddef:%s' % carddef.url_name}
|
||||
formdef.fields = [fields.ItemField(id='0', label='string', type='item',
|
||||
data_source=ds, display_disabled_items=True)]
|
||||
formdef.store()
|
||||
|
||||
resp = get_app(pub).get('/test/')
|
||||
assert resp.form['f0'].options == [
|
||||
(u'2', False, u'bar'),
|
||||
(u'3', False, u'baz'),
|
||||
(u'1', False, u'foo'),
|
||||
]
|
||||
resp.form['f0'] = '2'
|
||||
resp = resp.form.submit('submit') # -> validation page
|
||||
resp = resp.form.submit('submit') # -> submit
|
||||
assert formdef.data_class().select()[0].data['0'] == '2'
|
||||
assert formdef.data_class().select()[0].data['0_display'] == 'bar'
|
||||
assert formdef.data_class().select()[0].data['0_structured']['name'] == 'bar'
|
||||
|
||||
def test_item_field_with_disabled_items(http_requests, pub):
|
||||
user = create_user(pub)
|
||||
formdef = create_formdef()
|
||||
|
|
|
@ -29,3 +29,16 @@ class CardData(FormData):
|
|||
self._formdef = None
|
||||
return self._formdef
|
||||
formdef = property(get_formdef)
|
||||
|
||||
def get_data_source_structured_item(self):
|
||||
item = {
|
||||
'id': self.id,
|
||||
'text': self.digest,
|
||||
}
|
||||
for field in self.formdef.get_all_fields():
|
||||
if not field.varname:
|
||||
continue
|
||||
value = self.data and self.data.get(field.id)
|
||||
if isinstance(value, basestring):
|
||||
item[field.varname] = value
|
||||
return item
|
||||
|
|
|
@ -55,14 +55,21 @@ class DataSourceSelectionWidget(CompositeWidget):
|
|||
if not value:
|
||||
value = {}
|
||||
|
||||
options = [('none', _('None')),
|
||||
('formula', _('Python Expression')),
|
||||
('json', _('JSON URL'))]
|
||||
if allow_jsonp:
|
||||
options.append(('jsonp', _('JSONP URL')))
|
||||
options = []
|
||||
if allow_named_sources:
|
||||
options.extend([(x.slug, x.name) for x in
|
||||
NamedDataSource.select(order_by='name')])
|
||||
options.extend([(x.slug, x.name, x.slug) for x in NamedDataSource.select()])
|
||||
from wcs.carddef import CardDef
|
||||
options.extend([
|
||||
('carddef:%s' % x.url_name, x.name, 'carddef:%s' % x.url_name)
|
||||
for x in CardDef.select(lightweight=True, ignore_errors=True)
|
||||
if x.digest_template])
|
||||
options.sort(key=lambda x: qommon.misc.simplify(x[1]))
|
||||
|
||||
options.insert(0, (None, _('None'), None))
|
||||
options.append(('json', _('JSON URL'), 'json'))
|
||||
if allow_jsonp:
|
||||
options.append(('jsonp', _('JSONP URL'), 'jsonp'))
|
||||
options.append(('formula', _('Python Expression'), 'python'))
|
||||
|
||||
self.add(SingleSelectWidget, 'type', options=options, value=value.get('type'),
|
||||
attrs={'data-dynamic-display-parent': 'true'})
|
||||
|
@ -73,10 +80,7 @@ class DataSourceSelectionWidget(CompositeWidget):
|
|||
|
||||
self.add(StringWidget, 'value', value=value.get('value'), size=80,
|
||||
attrs={'data-dynamic-display-child-of': 'data_source$type',
|
||||
'data-dynamic-display-value-in': '|'.join(
|
||||
[_('Python Expression'),
|
||||
_('JSON URL'),
|
||||
_('JSONP URL')])})
|
||||
'data-dynamic-display-value-in': 'json|jsonp|python'})
|
||||
|
||||
self._parsed = False
|
||||
|
||||
|
@ -112,6 +116,17 @@ def get_items(data_source, include_disabled=False, mode=None):
|
|||
|
||||
def get_structured_items(data_source, mode=None):
|
||||
cache_duration = 0
|
||||
|
||||
if data_source.get('type') and data_source.get('type').startswith('carddef:'):
|
||||
# cards
|
||||
from wcs.carddef import CardDef
|
||||
carddef = CardDef.get_by_urlname(data_source['type'][8:])
|
||||
items = [x.get_data_source_structured_item()
|
||||
for x in carddef.data_class().select()
|
||||
if not x.is_draft()]
|
||||
items.sort(key=lambda x: qommon.misc.simplify(x['text']))
|
||||
return items
|
||||
|
||||
if data_source.get('type') not in ('json', 'jsonp', 'formula'):
|
||||
# named data source
|
||||
named_data_source = NamedDataSource.get_by_slug(data_source['type'])
|
||||
|
@ -214,6 +229,8 @@ def get_real(data_source):
|
|||
ds_type = data_source.get('type')
|
||||
if ds_type in ('json', 'jsonp', 'formula'):
|
||||
return data_source
|
||||
if ds_type and ds_type.startswith('carddef:'):
|
||||
return data_source
|
||||
return NamedDataSource.get_by_slug(ds_type).data_source
|
||||
|
||||
|
||||
|
@ -225,6 +242,10 @@ def get_object(data_source):
|
|||
named_data_source = NamedDataSource()
|
||||
named_data_source.data_source = data_source
|
||||
return named_data_source
|
||||
if ds_type.startswith('carddef:'):
|
||||
named_data_source = NamedDataSource()
|
||||
named_data_source.data_source = data_source
|
||||
return named_data_source
|
||||
return NamedDataSource.get_by_slug(ds_type)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue