misc: do not include gear dropdown when python is disabled (#73161) #23
|
@ -326,22 +326,17 @@ def test_data_sources_agenda_manual_qs_data_type_options(pub):
|
|||
with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd:
|
||||
pub.site_options.write(fd)
|
||||
|
||||
# check expression type is always forced (no python allowed).
|
||||
app = login(get_app(pub))
|
||||
resp = app.get('/backoffice/settings/data-sources/%s/edit' % data_source.id)
|
||||
assert resp.form['qs_data$element0value$type'].options == [
|
||||
('text', False, 'Text'),
|
||||
('template', False, 'Template'),
|
||||
]
|
||||
assert 'qs_data$element0value$type' not in resp.text
|
||||
|
||||
pub.site_options.set('options', 'disable-python-expressions', 'true')
|
||||
with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd:
|
||||
pub.site_options.write(fd)
|
||||
|
||||
resp = app.get('/backoffice/settings/data-sources/%s/edit' % data_source.id)
|
||||
assert resp.form['qs_data$element0value$type'].options == [
|
||||
('text', False, 'Text'),
|
||||
('template', False, 'Template'),
|
||||
]
|
||||
assert 'qs_data$element0value$type' not in resp.text
|
||||
|
||||
|
||||
def test_data_sources_category(pub):
|
||||
|
@ -863,7 +858,6 @@ def test_data_sources_agenda_manual_edit(pub):
|
|||
resp = app.get('/backoffice/settings/data-sources/%s/edit' % data_source.id)
|
||||
resp.forms[0]['qs_data$element0key'] = 'arg1'
|
||||
resp.forms[0]['qs_data$element0value$value_template'] = '{{ foobar }}'
|
||||
resp.forms[0]['qs_data$element0value$type'] = 'template'
|
||||
resp = resp.forms[0].submit('submit')
|
||||
|
||||
data_source = NamedDataSource.get(data_source.id)
|
||||
|
|
|
@ -2827,9 +2827,7 @@ def test_form_page_field_condition_types(pub):
|
|||
pub.site_options.write(fd)
|
||||
|
||||
resp = app.get('/backoffice/forms/1/fields/0/')
|
||||
assert resp.form['condition$type'].options == [
|
||||
('django', False, 'Django Expression'),
|
||||
]
|
||||
assert 'condition$type' not in resp.text
|
||||
|
||||
|
||||
def test_form_fields_reorder(pub):
|
||||
|
|
|
@ -1205,7 +1205,7 @@ def test_workflows_edit_email_action(pub):
|
|||
|
||||
resp = app.get(item_url)
|
||||
assert 'custom_from' in resp.text
|
||||
resp.form['custom_from$value_text'] = 'test@localhost'
|
||||
resp.form['custom_from$value_template'] = 'test@localhost'
|
||||
resp = resp.form.submit('submit')
|
||||
sendmail = Workflow.get(workflow.id).get_status(st1.id).items[0]
|
||||
assert sendmail.custom_from == 'test@localhost'
|
||||
|
@ -1217,7 +1217,7 @@ def test_workflows_edit_email_action(pub):
|
|||
|
||||
resp = app.get(item_url)
|
||||
assert 'custom_from' in resp.text
|
||||
assert resp.form['custom_from$value_text'].value == 'test@localhost'
|
||||
assert resp.form['custom_from$value_template'].value == 'test@localhost'
|
||||
|
||||
|
||||
def test_workflows_edit_jump_previous(pub):
|
||||
|
@ -1362,7 +1362,7 @@ def test_workflows_edit_sms_action(pub):
|
|||
resp = resp.form.submit('to$add_element')
|
||||
resp = resp.form.submit('to$add_element')
|
||||
resp = resp.form.submit('to$add_element')
|
||||
resp.form['to$element1$value_text'] = '12345'
|
||||
resp.form['to$element1$value_template'] = '12345'
|
||||
resp = resp.form.submit('submit')
|
||||
assert Workflow.get(workflow.id).possible_status[0].items[0].to == ['12345']
|
||||
|
||||
|
@ -1471,7 +1471,7 @@ def test_workflows_edit_display_form_action(pub):
|
|||
assert 'foobar' in resp.text
|
||||
resp = resp.click('Edit')
|
||||
assert 'display_locations' not in resp.form.fields.keys()
|
||||
assert 'condition$type' in resp.form.fields.keys()
|
||||
assert 'condition$value_django' in resp.form.fields.keys()
|
||||
resp = resp.form.submit('cancel')
|
||||
resp = resp.follow()
|
||||
resp = resp.click('Remove')
|
||||
|
@ -2115,7 +2115,7 @@ def test_workflows_backoffice_fields(pub):
|
|||
assert 'foobar3' not in options
|
||||
|
||||
resp.form['fields$element0$field_id'] = first_field_id
|
||||
resp.form['fields$element0$value$value_text'] = 'Hello'
|
||||
resp.form['fields$element0$value$value_template'] = 'Hello'
|
||||
resp = resp.form.submit('submit')
|
||||
workflow = Workflow.get(workflow.id)
|
||||
assert workflow.possible_status[0].items[0].fields == [{'field_id': first_field_id, 'value': 'Hello'}]
|
||||
|
@ -2905,7 +2905,6 @@ def test_workflows_create_formdata_expression_types(pub):
|
|||
app = login(get_app(pub))
|
||||
resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (wf.id, st1.id))
|
||||
assert resp.form['mappings$element0$expression$type'].options == [
|
||||
('text', False, 'Text'),
|
||||
('template', False, 'Template'),
|
||||
('python', False, 'Python Expression (deprecated)'),
|
||||
]
|
||||
|
@ -2915,10 +2914,7 @@ def test_workflows_create_formdata_expression_types(pub):
|
|||
pub.site_options.write(fd)
|
||||
|
||||
resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (wf.id, st1.id))
|
||||
assert resp.form['mappings$element0$expression$type'].options == [
|
||||
('text', False, 'Text'),
|
||||
('template', False, 'Template'),
|
||||
]
|
||||
assert 'mappings$element0$expression$type' not in resp.text
|
||||
|
||||
|
||||
def test_workflows_edit_carddata_action_config(pub):
|
||||
|
@ -3021,17 +3017,9 @@ def test_workflows_assign_carddata_action_options(pub):
|
|||
with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd:
|
||||
pub.site_options.write(fd)
|
||||
resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (wf.id, st.id))
|
||||
assert resp.form['target_id$type'].options == [
|
||||
('text', False, 'Text'),
|
||||
('template', False, 'Template'),
|
||||
]
|
||||
assert resp.form['user_association_template$type'].options == [
|
||||
('text', False, 'Text'),
|
||||
('template', False, 'Template'),
|
||||
]
|
||||
assert resp.form['condition$type'].options == [
|
||||
('django', False, 'Django Expression'),
|
||||
]
|
||||
assert 'target_id$type' not in resp.text
|
||||
assert 'user_association_template$type' not in resp.text
|
||||
assert 'condition$type' not in resp.text
|
||||
|
||||
|
||||
def test_workflows_assign_carddata_action(pub):
|
||||
|
@ -3070,7 +3058,6 @@ def test_workflows_assign_carddata_action(pub):
|
|||
|
||||
resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (wf.id, st.id))
|
||||
resp.forms[0]['target_mode'] = 'manual'
|
||||
resp.forms[0]['target_id$type'] = 'template'
|
||||
resp.forms[0]['target_id$value_template'] = '{{ form_var_plop_id }}'
|
||||
resp.forms[0]['user_association_mode'] = 'keep-user'
|
||||
resp = resp.forms[0].submit('submit')
|
||||
|
@ -3081,7 +3068,6 @@ def test_workflows_assign_carddata_action(pub):
|
|||
|
||||
resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (wf.id, st.id))
|
||||
resp.forms[0]['user_association_mode'] = 'custom'
|
||||
resp.forms[0]['user_association_template$type'] = 'template'
|
||||
resp.forms[0]['user_association_template$value_template'] = '{{ form_var_user_id }}'
|
||||
resp = resp.forms[0].submit('submit')
|
||||
assert Workflow.get(wf.id).possible_status[0].items[0].user_association_mode == 'custom'
|
||||
|
@ -3125,14 +3111,14 @@ def test_workflows_user_notification_action(pub):
|
|||
resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (wf.id, st.id))
|
||||
assert resp.forms[0]['to'].value == '_receiver'
|
||||
resp.forms[0]['to'] = '__other'
|
||||
resp.forms[0]['users_template$value_text'] = 'foobar'
|
||||
resp.forms[0]['users_template$value_template'] = 'foobar'
|
||||
resp = resp.forms[0].submit('submit')
|
||||
assert Workflow.get(wf.id).possible_status[0].items[0].to == []
|
||||
assert Workflow.get(wf.id).possible_status[0].items[0].users_template == 'foobar'
|
||||
|
||||
resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (wf.id, st.id))
|
||||
assert resp.forms[0]['to'].value == '__other'
|
||||
assert resp.forms[0]['users_template$value_text'].value == 'foobar'
|
||||
assert resp.forms[0]['users_template$value_template'].value == 'foobar'
|
||||
|
||||
resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (wf.id, st.id))
|
||||
resp.forms[0]['target_url'] = '{{portal_url}}'
|
||||
|
|
|
@ -12,6 +12,7 @@ from wcs.qommon.form import (
|
|||
CheckboxesWidget,
|
||||
CompositeWidget,
|
||||
ComputedExpressionWidget,
|
||||
ConditionWidget,
|
||||
DateWidget,
|
||||
EmailWidget,
|
||||
FileWithPreviewWidget,
|
||||
|
@ -702,12 +703,12 @@ def test_composite_widget():
|
|||
|
||||
def test_computed_expression_widget():
|
||||
widget = ComputedExpressionWidget('test')
|
||||
mock_form_submission(req, widget, {'test$value_text': 'hello world', 'test$type': ['text']})
|
||||
mock_form_submission(req, widget, {'test$value_template': 'hello world', 'test$type': ['template']})
|
||||
assert widget.parse() == 'hello world'
|
||||
assert not widget.has_error()
|
||||
|
||||
widget = ComputedExpressionWidget('test')
|
||||
mock_form_submission(req, widget, {'test$value_text': '', 'test$type': ['text']})
|
||||
mock_form_submission(req, widget, {'test$value_template': '', 'test$type': ['template']})
|
||||
assert widget.parse() is None
|
||||
assert not widget.has_error()
|
||||
|
||||
|
@ -1286,3 +1287,93 @@ def test_map_widget():
|
|||
def test_profile_fields_sorting():
|
||||
widget = ProfileUpdateRowWidget('profile')
|
||||
assert [f[1] for f in widget.get_widgets()[0].options] == ['Email', 'Name']
|
||||
|
||||
|
||||
def test_computed_expression_widget_no_python():
|
||||
pub.load_site_options()
|
||||
pub.site_options.set('options', 'disable-python-expressions', 'true')
|
||||
|
||||
widget = ComputedExpressionWidget('test')
|
||||
form = Form(method='post', use_tokens=False, enctype='application/x-www-form-urlencoded')
|
||||
form.widgets.append(widget)
|
||||
assert '$type' not in str(form.render())
|
||||
|
||||
widget = ComputedExpressionWidget('test')
|
||||
mock_form_submission(req, widget, {'test$value_template': 'hello world'})
|
||||
assert widget.parse() == 'hello world'
|
||||
assert not widget.has_error()
|
||||
|
||||
widget = ComputedExpressionWidget('test')
|
||||
mock_form_submission(req, widget, {'test$value_template': ''})
|
||||
assert widget.parse() is None
|
||||
assert not widget.has_error()
|
||||
|
||||
widget = ComputedExpressionWidget('test')
|
||||
mock_form_submission(req, widget, {'test$value_template': '{{ form_var_xxx }}'})
|
||||
assert not widget.has_error()
|
||||
|
||||
widget = ComputedExpressionWidget('test')
|
||||
mock_form_submission(req, widget, {'test$value_template': '{% if True %}'})
|
||||
assert widget.has_error()
|
||||
assert widget.get_error().startswith('syntax error in Django template')
|
||||
|
||||
pub.site_options.set('options', 'disable-python-expressions', 'false')
|
||||
|
||||
|
||||
def test_condition_widget():
|
||||
widget = ConditionWidget('test')
|
||||
form = Form(method='post', use_tokens=False, enctype='application/x-www-form-urlencoded')
|
||||
form.widgets.append(widget)
|
||||
assert '$type' in str(form.render())
|
||||
|
||||
widget = ConditionWidget('test')
|
||||
mock_form_submission(req, widget, {'test$value_django': 'hello == 1'})
|
||||
assert widget.parse() == {'type': 'django', 'value': 'hello == 1'}
|
||||
assert not widget.has_error()
|
||||
|
||||
widget = ConditionWidget('test')
|
||||
mock_form_submission(req, widget, {'test$value_django': ''})
|
||||
assert widget.parse() is None
|
||||
assert not widget.has_error()
|
||||
|
||||
widget = ConditionWidget('test')
|
||||
mock_form_submission(req, widget, {'test$value_django': '{{ form_var_xxx }}'})
|
||||
assert widget.has_error()
|
||||
assert widget.get_error() == "syntax error: Could not parse the remainder: '{{' from '{{'"
|
||||
|
||||
widget = ConditionWidget('test')
|
||||
mock_form_submission(req, widget, {'test$value_python': 'hello == 1', 'test$type': ['python']})
|
||||
assert widget.parse() == {'type': 'python', 'value': 'hello == 1'}
|
||||
assert not widget.has_error()
|
||||
|
||||
widget = ConditionWidget('test')
|
||||
mock_form_submission(req, widget, {'test$value_python': 'hello~', 'test$type': ['python']})
|
||||
assert widget.has_error()
|
||||
assert widget.get_error().startswith('syntax error:')
|
||||
|
||||
|
||||
def test_condition_widget_no_python():
|
||||
pub.load_site_options()
|
||||
pub.site_options.set('options', 'disable-python-expressions', 'true')
|
||||
|
||||
widget = ConditionWidget('test')
|
||||
form = Form(method='post', use_tokens=False, enctype='application/x-www-form-urlencoded')
|
||||
form.widgets.append(widget)
|
||||
assert '$type' not in str(form.render())
|
||||
|
||||
widget = ConditionWidget('test')
|
||||
mock_form_submission(req, widget, {'test$value_django': 'hello == 1'})
|
||||
assert widget.parse() == {'type': 'django', 'value': 'hello == 1'}
|
||||
assert not widget.has_error()
|
||||
|
||||
widget = ConditionWidget('test')
|
||||
mock_form_submission(req, widget, {'test$value_django': ''})
|
||||
assert widget.parse() is None
|
||||
assert not widget.has_error()
|
||||
|
||||
widget = ConditionWidget('test')
|
||||
mock_form_submission(req, widget, {'test$value_django': '{{ form_var_xxx }}'})
|
||||
assert widget.has_error()
|
||||
assert widget.get_error() == "syntax error: Could not parse the remainder: '{{' from '{{'"
|
||||
|
||||
pub.site_options.set('options', 'disable-python-expressions', 'false')
|
||||
|
|
|
@ -3333,26 +3333,13 @@ class ComputedExpressionWidget(CompositeWidget):
|
|||
from wcs.workflows import WorkflowStatusItem
|
||||
|
||||
value = WorkflowStatusItem.get_expression(value)
|
||||
if value.get('type') == 'text':
|
||||
value['type'] = 'template'
|
||||
|
||||
value_placeholder = kwargs.pop('value_placeholder', None)
|
||||
self.allow_python = kwargs.pop('allow_python', True)
|
||||
CompositeWidget.__init__(self, name, value, **kwargs)
|
||||
|
||||
options = [
|
||||
('text', _('Text'), 'text'),
|
||||
('template', _('Template'), 'template'),
|
||||
]
|
||||
if self.allow_python and not get_publisher().has_site_option('disable-python-expressions'):
|
||||
options.append(('python', _('Python Expression (deprecated)'), 'python'))
|
||||
|
||||
self.add(
|
||||
StringWidget,
|
||||
'value_text',
|
||||
size=80,
|
||||
value=value.get('value') if value.get('type') == 'text' else None,
|
||||
placeholder=value_placeholder,
|
||||
)
|
||||
|
||||
self.add(
|
||||
StringWidget,
|
||||
'value_template',
|
||||
|
@ -3361,47 +3348,58 @@ class ComputedExpressionWidget(CompositeWidget):
|
|||
placeholder=value_placeholder,
|
||||
)
|
||||
|
||||
self.add(
|
||||
StringWidget,
|
||||
'value_python',
|
||||
size=80,
|
||||
value=value.get('value') if value.get('type') == 'python' else None,
|
||||
placeholder=value_placeholder,
|
||||
)
|
||||
|
||||
self.add(
|
||||
SingleSelectWidget,
|
||||
'type',
|
||||
options=options,
|
||||
value=value.get('type'),
|
||||
attrs={'data-dynamic-display-parent': 'true'},
|
||||
)
|
||||
self.has_python = False
|
||||
if self.allow_python and not get_publisher().has_site_option('disable-python-expressions'):
|
||||
self.has_python = True
|
||||
self.add(
|
||||
StringWidget,
|
||||
'value_python',
|
||||
size=80,
|
||||
value=value.get('value') if value.get('type') == 'python' else None,
|
||||
placeholder=value_placeholder,
|
||||
)
|
||||
self.add(
|
||||
SingleSelectWidget,
|
||||
'type',
|
||||
options=[
|
||||
('template', _('Template'), 'template'),
|
||||
('python', _('Python Expression (deprecated)'), 'python'),
|
||||
],
|
||||
value=value.get('type'),
|
||||
attrs={'data-dynamic-display-parent': 'true'},
|
||||
)
|
||||
|
||||
def render_content(self):
|
||||
ctx = {
|
||||
'name': self.name,
|
||||
'text_label': _('Text'),
|
||||
'template_label': _('Template'),
|
||||
'python_label': _('Python'),
|
||||
'value_text': self.get_widget('value_text').render_content(),
|
||||
'value_template': self.get_widget('value_template').render_content(),
|
||||
'value_python': self.get_widget('value_python').render_content(),
|
||||
'type': self.get_widget('type').render_content(),
|
||||
}
|
||||
if not self.has_python:
|
||||
return (
|
||||
htmltext(
|
||||
'''\
|
||||
<style>span[data-name="%(name)s"].template::after { content: "%(template_label)s"; }</style>
|
||||
<span class="template only" data-name="%(name)s">%(value_template)s</span>'''
|
||||
)
|
||||
% ctx
|
||||
)
|
||||
|
||||
ctx.update(
|
||||
{
|
||||
'python_label': _('Python'),
|
||||
'type': self.get_widget('type').render_content(),
|
||||
'value_python': self.get_widget('value_python').render_content(),
|
||||
}
|
||||
)
|
||||
return (
|
||||
htmltext(
|
||||
'''
|
||||
<style>
|
||||
span[data-name="%(name)s"].text::after { content: "%(text_label)s"; }
|
||||
span[data-name="%(name)s"].template::after { content: "%(template_label)s"; }
|
||||
span[data-name="%(name)s"].python::after { content: "%(python_label)s"; }
|
||||
</style>
|
||||
<span class="text"
|
||||
data-name="%(name)s"
|
||||
data-dynamic-display-value="text"
|
||||
data-dynamic-display-child-of="%(name)s$type"
|
||||
>%(value_text)s</span
|
||||
><span class="template"
|
||||
<span class="template"
|
||||
data-name="%(name)s"
|
||||
data-dynamic-display-value="template"
|
||||
data-dynamic-display-child-of="%(name)s$type"
|
||||
|
@ -3442,9 +3440,12 @@ class ComputedExpressionWidget(CompositeWidget):
|
|||
|
||||
def _parse(self, request):
|
||||
self.value = None
|
||||
if not self.get('type'):
|
||||
return
|
||||
value_type = self.get('type')
|
||||
if self.has_python:
|
||||
if not self.get('type'):
|
||||
return
|
||||
value_type = self.get('type')
|
||||
else:
|
||||
value_type = 'template'
|
||||
value_content = self.get('value_%s' % value_type)
|
||||
if value_type == 'python' and value_content:
|
||||
self.value = '=' + (value_content or '')
|
||||
|
@ -3464,12 +3465,7 @@ class ConditionWidget(CompositeWidget):
|
|||
if not value:
|
||||
value = {}
|
||||
|
||||
options = []
|
||||
options.append(('django', _('Django Expression'), 'django'))
|
||||
if kwargs.get('allow_python', True) and not get_publisher().has_site_option(
|
||||
'disable-python-expressions'
|
||||
):
|
||||
options.append(('python', _('Python Expression (deprecated)'), 'python'))
|
||||
self.has_python = False
|
||||
|
||||
self.add(
|
||||
StringWidget,
|
||||
|
@ -3478,20 +3474,26 @@ class ConditionWidget(CompositeWidget):
|
|||
value=value.get('value') if value.get('type') == 'django' else None,
|
||||
)
|
||||
|
||||
self.add(
|
||||
StringWidget,
|
||||
'value_python',
|
||||
size=80,
|
||||
value=value.get('value') if value.get('type') == 'python' else None,
|
||||
)
|
||||
|
||||
self.add(
|
||||
SingleSelectWidget,
|
||||
'type',
|
||||
options=options,
|
||||
value=value.get('type'),
|
||||
attrs={'data-dynamic-display-parent': 'true'},
|
||||
)
|
||||
if kwargs.get('allow_python', True) and not get_publisher().has_site_option(
|
||||
'disable-python-expressions'
|
||||
):
|
||||
self.has_python = True
|
||||
self.add(
|
||||
StringWidget,
|
||||
'value_python',
|
||||
size=80,
|
||||
value=value.get('value') if value.get('type') == 'python' else None,
|
||||
)
|
||||
self.add(
|
||||
SingleSelectWidget,
|
||||
'type',
|
||||
options=[
|
||||
('django', _('Django Expression'), 'django'),
|
||||
('python', _('Python Expression (deprecated)'), 'python'),
|
||||
],
|
||||
value=value.get('type'),
|
||||
attrs={'data-dynamic-display-parent': 'true'},
|
||||
)
|
||||
|
||||
@property
|
||||
def content_extra_attributes(self):
|
||||
|
@ -3500,14 +3502,14 @@ class ConditionWidget(CompositeWidget):
|
|||
|
||||
def _parse(self, request):
|
||||
self.value = None
|
||||
if not self.get('type') or self.get('type') == 'none':
|
||||
return
|
||||
if self.has_python:
|
||||
if not self.get('type') or self.get('type') == 'none':
|
||||
return
|
||||
self.value = {'type': self.get('type')}
|
||||
else:
|
||||
self.value = {'type': 'django'}
|
||||
|
||||
self.value = {}
|
||||
self.value['type'] = self.get('type')
|
||||
|
||||
if self.value['type']:
|
||||
self.value['value'] = self.get('value_%s' % self.value['type'])
|
||||
self.value['value'] = self.get('value_%s' % self.value['type'])
|
||||
|
||||
if self.value['value']:
|
||||
try:
|
||||
|
@ -3521,9 +3523,16 @@ class ConditionWidget(CompositeWidget):
|
|||
ctx = {
|
||||
'name': self.name,
|
||||
'value_django': self.get_widget('value_django').render_content(),
|
||||
'value_python': self.get_widget('value_python').render_content(),
|
||||
'type': self.get_widget('type').render_content(),
|
||||
}
|
||||
if not self.has_python:
|
||||
return htmltext('<span class="django only">%(value_django)s</span>') % ctx
|
||||
|
||||
ctx.update(
|
||||
{
|
||||
'value_python': self.get_widget('value_python').render_content(),
|
||||
'type': self.get_widget('type').render_content(),
|
||||
}
|
||||
)
|
||||
return (
|
||||
htmltext(
|
||||
'''
|
||||
|
|
|
@ -1057,6 +1057,11 @@ div.ConditionWidget div.content input[type=text] {
|
|||
width: calc(100% - 2.7em);
|
||||
}
|
||||
|
||||
div.ComputedExpressionWidget div.content span.only input[type=text],
|
||||
div.ConditionWidget div.content span.only input[type=text] {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.ComputedExpressionWidget div.content span,
|
||||
div.ConditionWidget div.content span.django,
|
||||
div.ConditionWidget div.content span.python {
|
||||
|
|
Loading…
Reference in New Issue