commit
e718dd7b25
@ -15,6 +15,7 @@ Files:
|
||||
Other:
|
||||
- Changed widget api. Used new metaclass.
|
||||
- Changed api for plugins.
|
||||
- Renamed config api classes.
|
||||
|
||||
|
||||
Version 1.5.1 (unreleased)
|
||||
|
@ -11,7 +11,7 @@ from django.template.loader import render_to_string
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext_lazy, ugettext_noop
|
||||
|
||||
from openslides.config.api import config, ConfigPage, ConfigVariable
|
||||
from openslides.config.api import config, ConfigCollection, ConfigVariable
|
||||
from openslides.config.signals import config_signal
|
||||
from openslides.projector.api import get_active_slide, get_active_object
|
||||
from openslides.projector.projector import Overlay
|
||||
@ -29,8 +29,8 @@ def validate_start_time(value):
|
||||
|
||||
# TODO: Reinsert the datepicker scripts in the template
|
||||
|
||||
@receiver(config_signal, dispatch_uid='setup_agenda_config_page')
|
||||
def setup_agenda_config_page(sender, **kwargs):
|
||||
@receiver(config_signal, dispatch_uid='setup_agenda_config')
|
||||
def setup_agenda_config(sender, **kwargs):
|
||||
"""
|
||||
Agenda config variables.
|
||||
"""
|
||||
@ -66,7 +66,7 @@ def setup_agenda_config_page(sender, **kwargs):
|
||||
'javascript/jquery-ui-sliderAccess.min.js',
|
||||
'javascript/agenda-config-datepicker.js']
|
||||
|
||||
return ConfigPage(title=ugettext_noop('Agenda'),
|
||||
return ConfigCollection(title=ugettext_noop('Agenda'),
|
||||
url='agenda',
|
||||
required_permission='config.can_manage',
|
||||
weight=20,
|
||||
|
@ -5,12 +5,12 @@ from django.dispatch import receiver
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext_lazy, ugettext_noop
|
||||
|
||||
from openslides.config.api import ConfigPage, ConfigVariable
|
||||
from openslides.config.api import ConfigCollection, ConfigVariable
|
||||
from openslides.config.signals import config_signal
|
||||
|
||||
|
||||
@receiver(config_signal, dispatch_uid='setup_assignment_config_page')
|
||||
def setup_assignment_config_page(sender, **kwargs):
|
||||
@receiver(config_signal, dispatch_uid='setup_assignment_config')
|
||||
def setup_assignment_config(sender, **kwargs):
|
||||
"""
|
||||
Assignment config variables.
|
||||
"""
|
||||
@ -66,7 +66,7 @@ def setup_assignment_config_page(sender, **kwargs):
|
||||
('votes', ugettext_lazy('Always one option per candidate')),
|
||||
('yesnoabstain', ugettext_lazy('Always Yes-No-Abstain per candidate')))))
|
||||
|
||||
return ConfigPage(title=ugettext_noop('Elections'),
|
||||
return ConfigCollection(title=ugettext_noop('Elections'),
|
||||
url='assignment',
|
||||
required_permission='config.can_manage',
|
||||
weight=40,
|
||||
|
@ -35,8 +35,8 @@ class ConfigHandler(object):
|
||||
pass
|
||||
|
||||
# Call on_change callback
|
||||
for receiver, config_page in config_signal.send(sender='set_value'):
|
||||
for config_variable in config_page.variables:
|
||||
for receiver, config_collection in config_signal.send(sender='set_value'):
|
||||
for config_variable in config_collection.variables:
|
||||
if config_variable.name == key and config_variable.on_change:
|
||||
config_variable.on_change()
|
||||
break
|
||||
@ -45,8 +45,8 @@ class ConfigHandler(object):
|
||||
"""
|
||||
Returns the default value for 'key'.
|
||||
"""
|
||||
for receiver, config_page in config_signal.send(sender='get_default'):
|
||||
for config_variable in config_page.variables:
|
||||
for receiver, config_collection in config_signal.send(sender='get_default'):
|
||||
for config_variable in config_collection.variables:
|
||||
if config_variable.name == key:
|
||||
return config_variable.default_value
|
||||
raise ConfigNotFound('The config variable %s was not found.' % key)
|
||||
@ -57,8 +57,8 @@ class ConfigHandler(object):
|
||||
signal to get the default into the cache.
|
||||
"""
|
||||
self._cache = {}
|
||||
for receiver, config_page in config_signal.send(sender='setup_cache'):
|
||||
for config_variable in config_page.variables:
|
||||
for receiver, config_collection in config_signal.send(sender='setup_cache'):
|
||||
for config_variable in config_collection.variables:
|
||||
if config_variable.name in self._cache:
|
||||
raise ConfigError('Too many values for config variable %s found.' % config_variable.name)
|
||||
self._cache[config_variable.name] = config_variable.default_value
|
||||
@ -81,15 +81,17 @@ use x = config[...], to set it use config[...] = x.
|
||||
"""
|
||||
|
||||
|
||||
class ConfigBasePage(object):
|
||||
class ConfigBaseCollection(object):
|
||||
"""
|
||||
An abstract base class for simple and grouped config pages. The
|
||||
attributes title and url are required. The attribute weight is used
|
||||
for the order of the links in the submenu of the views. The attribute
|
||||
extra_context can be used to insert extra css and js files into the
|
||||
template.
|
||||
An abstract base class for simple and grouped config collections. The
|
||||
attributes title and url are required for collections that should be
|
||||
shown as a view. The attribute required_permission is used to set which
|
||||
users can control the view showing the colletion. The attribute weight
|
||||
is used for the order of the links in the submenu of the views. The
|
||||
attribute extra_context can be used to insert extra css and js files
|
||||
into the template.
|
||||
"""
|
||||
def __init__(self, title, url, required_permission=None, weight=0, extra_context={}):
|
||||
def __init__(self, title=None, url=None, required_permission=None, weight=0, extra_context={}):
|
||||
self.title = title
|
||||
self.url = url
|
||||
self.required_permission = required_permission
|
||||
@ -98,25 +100,29 @@ class ConfigBasePage(object):
|
||||
|
||||
def is_shown(self):
|
||||
"""
|
||||
Returns True if at least one variable of the page has a form field.
|
||||
Returns True if at least one variable of the collection has a form field.
|
||||
"""
|
||||
for variable in self.variables:
|
||||
if variable.form_field is not None:
|
||||
return True
|
||||
is_shown = True
|
||||
break
|
||||
else:
|
||||
return False
|
||||
is_shown = False
|
||||
if is_shown and (self.title is None or self.url is None):
|
||||
raise ConfigError('The config collection %s must have a title and an url attribute.' % self)
|
||||
return is_shown
|
||||
|
||||
|
||||
class ConfigGroupedPage(ConfigBasePage):
|
||||
class ConfigGroupedCollection(ConfigBaseCollection):
|
||||
"""
|
||||
A simple object class for a grouped config page. Developers have to
|
||||
A simple object class for a grouped config collection. Developers have to
|
||||
set the groups attribute (tuple). The config variables are available
|
||||
via the variables attribute. The page is shown as view in the config
|
||||
tab, if there is at least one variable with a form field.
|
||||
via the variables attribute. The collection is shown as a view via the config
|
||||
main menu entry if there is at least one variable with a form field.
|
||||
"""
|
||||
def __init__(self, groups, **kwargs):
|
||||
self.groups = groups
|
||||
super(ConfigGroupedPage, self).__init__(**kwargs)
|
||||
super(ConfigGroupedCollection, self).__init__(**kwargs)
|
||||
|
||||
@property
|
||||
def variables(self):
|
||||
@ -125,15 +131,16 @@ class ConfigGroupedPage(ConfigBasePage):
|
||||
yield variable
|
||||
|
||||
|
||||
class ConfigPage(ConfigBasePage):
|
||||
class ConfigCollection(ConfigBaseCollection):
|
||||
"""
|
||||
A simple object class for a ungrouped config page. Developers have
|
||||
to set the variables (tuple) directly. The page is shown as view in
|
||||
the config tab, if there is at least one variable with a form field.
|
||||
A simple object class for a ungrouped config collection. Developers have
|
||||
to set the variables (tuple) directly. The collection is shown as a view via
|
||||
the config main menu entry if there is at least one variable with a
|
||||
form field.
|
||||
"""
|
||||
def __init__(self, variables, **kwargs):
|
||||
self.variables = variables
|
||||
super(ConfigPage, self).__init__(**kwargs)
|
||||
super(ConfigCollection, self).__init__(**kwargs)
|
||||
|
||||
|
||||
class ConfigGroup(object):
|
||||
@ -153,7 +160,7 @@ class ConfigVariable(object):
|
||||
"""
|
||||
A simple object class to wrap new config variables. The keyword
|
||||
arguments 'name' and 'default_value' are required. The keyword
|
||||
argument 'form_field' has to be set, if the variable should appear
|
||||
argument 'form_field' has to be set if the variable should appear
|
||||
on the ConfigView. The argument 'on_change' can get a callback
|
||||
which is called every time, the variable is changed.
|
||||
"""
|
||||
|
@ -8,12 +8,14 @@
|
||||
{% block content %}
|
||||
<h1>
|
||||
{% trans 'Configuration' %}
|
||||
<small>{% trans active_config_page.title %}</small>
|
||||
<small>{% trans active_config_collection_view.title %}</small>
|
||||
<small class="pull-right">
|
||||
<div class="btn-toolbar">
|
||||
<div class="btn-group">
|
||||
{% for config_page_dict in config_pages_list %}
|
||||
<a href="/config/{{ config_page_dict.config_page.url }}/" class="btn btn-mini {% if config_page_dict.active %}active{% endif %}">{% trans config_page_dict.config_page.title %}</a>
|
||||
{% for config_collection_dict in config_collection_list %}
|
||||
<a href="/config/{{ config_collection_dict.config_collection.url }}/" class="btn btn-mini {% if config_collection_dict.active %}active{% endif %}">
|
||||
{% trans config_collection_dict.config_collection.title %}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
@ -43,7 +45,7 @@
|
||||
{% endfor %}
|
||||
<p>
|
||||
{% include 'formbuttons_save.html' %}
|
||||
<a href="/config/{{ active_config_page.url }}/" class="btn">{% trans 'Cancel' %}</a>
|
||||
<a href="/config/{{ active_config_collection_view.url }}/" class="btn">{% trans 'Cancel' %}</a>
|
||||
</p>
|
||||
<small>* {% trans 'required' %}</small>
|
||||
</form>
|
||||
|
@ -11,11 +11,11 @@ urlpatterns = patterns(
|
||||
'',
|
||||
url(r'^$',
|
||||
RedirectView.as_view(url_name='config_general'),
|
||||
name='config_first_config_page')
|
||||
name='config_first_config_collection_view')
|
||||
)
|
||||
|
||||
for receiver, config_page in config_signal.send(sender='config_urls'):
|
||||
if config_page.is_shown():
|
||||
urlpatterns += patterns('', url(r'^%s/$' % config_page.url,
|
||||
ConfigView.as_view(config_page=config_page),
|
||||
name='config_%s' % config_page.url))
|
||||
for receiver, config_collection in config_signal.send(sender='config_urls'):
|
||||
if config_collection.is_shown():
|
||||
urlpatterns += patterns('', url(r'^%s/$' % config_collection.url,
|
||||
ConfigView.as_view(config_collection=config_collection),
|
||||
name='config_%s' % config_collection.url))
|
||||
|
@ -14,34 +14,34 @@ from .signals import config_signal
|
||||
|
||||
class ConfigView(FormView):
|
||||
"""
|
||||
The view for a config page.
|
||||
The view for a config collection.
|
||||
"""
|
||||
template_name = 'config/config_form.html'
|
||||
config_page = None
|
||||
config_collection = None
|
||||
form_class = forms.Form
|
||||
|
||||
def has_permission(self, *args, **kwargs):
|
||||
"""
|
||||
Ensures that only users with tab's permission can see this view.
|
||||
Ensures that only users with permission can see this view.
|
||||
"""
|
||||
self.permission_required = self.config_page.required_permission
|
||||
self.permission_required = self.config_collection.required_permission
|
||||
return super(ConfigView, self).has_permission(*args, **kwargs)
|
||||
|
||||
def get_form(self, *args):
|
||||
"""
|
||||
Gets the form for the view. Includes all form fields given by the
|
||||
tab's config objects.
|
||||
config collection.
|
||||
"""
|
||||
form = super(ConfigView, self).get_form(*args)
|
||||
for name, field in self.generate_form_fields_from_config_page():
|
||||
for name, field in self.generate_form_fields_from_config_collection():
|
||||
form.fields[name] = field
|
||||
return form
|
||||
|
||||
def generate_form_fields_from_config_page(self):
|
||||
def generate_form_fields_from_config_collection(self):
|
||||
"""
|
||||
Generates the fields for the get_form function.
|
||||
"""
|
||||
for variable in self.config_page.variables:
|
||||
for variable in self.config_collection.variables:
|
||||
if variable.form_field is not None:
|
||||
yield (variable.name, variable.form_field)
|
||||
|
||||
@ -51,54 +51,55 @@ class ConfigView(FormView):
|
||||
as intial value for the form.
|
||||
"""
|
||||
initial = super(ConfigView, self).get_initial()
|
||||
for variable in self.config_page.variables:
|
||||
for variable in self.config_collection.variables:
|
||||
initial.update({variable.name: config[variable.name]})
|
||||
return initial
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""
|
||||
Adds to the context the active config tab, a list of dictionaries
|
||||
containing all config tabs each with a flag which is true if the
|
||||
tab is the active one and adds a flag whether the config page has
|
||||
groups. Adds also extra_stylefiles and extra_javascript.
|
||||
Adds to the context the active config view, a list of dictionaries
|
||||
containing all config collections each with a flag which is true if its
|
||||
view is the active one and adds a flag whether the config collection
|
||||
has groups. Adds also extra_stylefiles and extra_javascript.
|
||||
"""
|
||||
context = super(ConfigView, self).get_context_data(**kwargs)
|
||||
|
||||
context['active_config_page'] = self.config_page
|
||||
context['active_config_collection_view'] = self.config_collection
|
||||
|
||||
config_pages_list = []
|
||||
for receiver, config_page in config_signal.send(sender=self):
|
||||
if config_page.is_shown():
|
||||
config_pages_list.append({
|
||||
'config_page': config_page,
|
||||
'active': self.request.path == reverse('config_%s' % config_page.url)})
|
||||
context['config_pages_list'] = sorted(config_pages_list, key=lambda config_page_dict: config_page_dict['config_page'].weight)
|
||||
config_collection_list = []
|
||||
for receiver, config_collection in config_signal.send(sender=self):
|
||||
if config_collection.is_shown():
|
||||
config_collection_list.append({
|
||||
'config_collection': config_collection,
|
||||
'active': self.request.path == reverse('config_%s' % config_collection.url)})
|
||||
context['config_collection_list'] = sorted(
|
||||
config_collection_list, key=lambda config_collection_dict: config_collection_dict['config_collection'].weight)
|
||||
|
||||
if hasattr(self.config_page, 'groups'):
|
||||
context['groups'] = self.config_page.groups
|
||||
if hasattr(self.config_collection, 'groups'):
|
||||
context['groups'] = self.config_collection.groups
|
||||
else:
|
||||
context['groups'] = None
|
||||
|
||||
if 'extra_stylefiles' in self.config_page.extra_context:
|
||||
if 'extra_stylefiles' in self.config_collection.extra_context:
|
||||
if 'extra_stylefiles' in context:
|
||||
context['extra_stylefiles'].extend(self.config_page.extra_context['extra_stylefiles'])
|
||||
context['extra_stylefiles'].extend(self.config_collection.extra_context['extra_stylefiles'])
|
||||
else:
|
||||
context['extra_stylefiles'] = self.config_page.extra_context['extra_stylefiles']
|
||||
context['extra_stylefiles'] = self.config_collection.extra_context['extra_stylefiles']
|
||||
|
||||
if 'extra_javascript' in self.config_page.extra_context:
|
||||
if 'extra_javascript' in self.config_collection.extra_context:
|
||||
if 'extra_javascript' in context:
|
||||
context['extra_javascript'].extend(self.config_page.extra_context['extra_javascript'])
|
||||
context['extra_javascript'].extend(self.config_collection.extra_context['extra_javascript'])
|
||||
else:
|
||||
context['extra_javascript'] = self.config_page.extra_context['extra_javascript']
|
||||
context['extra_javascript'] = self.config_collection.extra_context['extra_javascript']
|
||||
|
||||
return context
|
||||
|
||||
def get_success_url(self):
|
||||
"""
|
||||
Returns the success url when changes are saved. Here it is the same
|
||||
url as the tab.
|
||||
url as the main menu entry.
|
||||
"""
|
||||
return reverse('config_%s' % self.config_page.url)
|
||||
return reverse('config_%s' % self.config_collection.url)
|
||||
|
||||
def form_valid(self, form):
|
||||
"""
|
||||
@ -106,17 +107,17 @@ class ConfigView(FormView):
|
||||
"""
|
||||
for key in form.cleaned_data:
|
||||
config[key] = form.cleaned_data[key]
|
||||
messages.success(self.request, _('%s settings successfully saved.') % _(self.config_page.title))
|
||||
messages.success(self.request, _('%s settings successfully saved.') % _(self.config_collection.title))
|
||||
return super(ConfigView, self).form_valid(form)
|
||||
|
||||
|
||||
def register_tab(request):
|
||||
"""
|
||||
Registers the tab for this app in the main menu.
|
||||
Registers the entry for this app in the main menu.
|
||||
"""
|
||||
return Tab(
|
||||
title=_('Configuration'),
|
||||
app='config',
|
||||
url=reverse('config_first_config_page'),
|
||||
url=reverse('config_first_config_collection_view'),
|
||||
permission=request.user.has_perm('config.can_manage'),
|
||||
selected=request.path.startswith('/config/'))
|
||||
|
@ -5,15 +5,15 @@ from django.dispatch import receiver, Signal
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext_lazy, ugettext_noop
|
||||
|
||||
from openslides.config.api import ConfigGroup, ConfigGroupedPage, ConfigVariable
|
||||
from openslides.config.api import ConfigGroup, ConfigGroupedCollection, ConfigVariable
|
||||
from openslides.config.signals import config_signal
|
||||
from openslides.projector.api import update_projector
|
||||
|
||||
post_database_setup = Signal()
|
||||
|
||||
|
||||
@receiver(config_signal, dispatch_uid='setup_general_config_page')
|
||||
def setup_general_config_page(sender, **kwargs):
|
||||
@receiver(config_signal, dispatch_uid='setup_general_config')
|
||||
def setup_general_config(sender, **kwargs):
|
||||
"""
|
||||
General config variables for OpenSlides. They are grouped in 'Event',
|
||||
'Welcome Widget' and 'System'.
|
||||
@ -182,7 +182,7 @@ def setup_general_config_page(sender, **kwargs):
|
||||
title=ugettext_lazy('System'),
|
||||
variables=(system_enable_anonymous, system_url, system_wlan_ssid, system_wlan_password, system_wlan_encryption))
|
||||
|
||||
return ConfigGroupedPage(
|
||||
return ConfigGroupedCollection(
|
||||
title=ugettext_noop('General'),
|
||||
url='general',
|
||||
required_permission='config.can_manage',
|
||||
|
@ -5,15 +5,15 @@ from django.dispatch import receiver
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext_lazy, ugettext_noop
|
||||
|
||||
from openslides.config.api import ConfigPage, ConfigVariable
|
||||
from openslides.config.api import ConfigCollection, ConfigVariable
|
||||
from openslides.config.signals import config_signal
|
||||
from openslides.core.signals import post_database_setup
|
||||
|
||||
from .models import State, Workflow
|
||||
|
||||
|
||||
@receiver(config_signal, dispatch_uid='setup_motion_config_page')
|
||||
def setup_motion_config_page(sender, **kwargs):
|
||||
@receiver(config_signal, dispatch_uid='setup_motion_config')
|
||||
def setup_motion_config(sender, **kwargs):
|
||||
"""
|
||||
Motion config variables.
|
||||
"""
|
||||
@ -109,7 +109,7 @@ def setup_motion_config_page(sender, **kwargs):
|
||||
('serially_numbered', ugettext_lazy('Serially numbered')),
|
||||
('manually', ugettext_lazy('Set it manually'))]))
|
||||
|
||||
return ConfigPage(title=ugettext_noop('Motion'),
|
||||
return ConfigCollection(title=ugettext_noop('Motion'),
|
||||
url='motion',
|
||||
required_permission='config.can_manage',
|
||||
weight=30,
|
||||
|
@ -7,7 +7,7 @@ from django.dispatch import receiver
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext_lazy, ugettext_noop
|
||||
|
||||
from openslides.config.api import ConfigPage, ConfigVariable
|
||||
from openslides.config.api import ConfigCollection, ConfigVariable
|
||||
from openslides.config.signals import config_signal
|
||||
from openslides.core.signals import post_database_setup
|
||||
|
||||
@ -15,8 +15,8 @@ from .api import create_or_reset_admin_user
|
||||
from .models import Group
|
||||
|
||||
|
||||
@receiver(config_signal, dispatch_uid='setup_participant_config_page')
|
||||
def setup_participant_config_page(sender, **kwargs):
|
||||
@receiver(config_signal, dispatch_uid='setup_participant_config')
|
||||
def setup_participant_config(sender, **kwargs):
|
||||
"""
|
||||
Participant config variables.
|
||||
"""
|
||||
@ -44,7 +44,7 @@ def setup_participant_config_page(sender, **kwargs):
|
||||
label=ugettext_lazy('Sort participants by first name'),
|
||||
help_text=ugettext_lazy('Disable for sorting by last name')))
|
||||
|
||||
return ConfigPage(title=ugettext_noop('Participant'),
|
||||
return ConfigCollection(title=ugettext_noop('Participant'),
|
||||
url='participant',
|
||||
required_permission='config.can_manage',
|
||||
weight=50,
|
||||
|
@ -7,7 +7,7 @@ from django.dispatch import receiver, Signal
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.datastructures import SortedDict
|
||||
|
||||
from openslides.config.api import config, ConfigPage, ConfigVariable
|
||||
from openslides.config.api import config, ConfigCollection, ConfigVariable
|
||||
from openslides.config.signals import config_signal
|
||||
|
||||
from .projector import Overlay
|
||||
@ -15,13 +15,12 @@ from .projector import Overlay
|
||||
projector_overlays = Signal(providing_args=['request'])
|
||||
|
||||
|
||||
@receiver(config_signal, dispatch_uid='setup_projector_config_variables')
|
||||
def config_variables(sender, **kwargs):
|
||||
@receiver(config_signal, dispatch_uid='setup_projector_config')
|
||||
def setup_projector_config(sender, **kwargs):
|
||||
"""
|
||||
Projector config variables for OpenSlides. They are not shown on a
|
||||
config page.
|
||||
config view.
|
||||
"""
|
||||
|
||||
# The active slide. The config-value is a dictonary with at least the entry
|
||||
# 'callback'.
|
||||
projector = ConfigVariable(
|
||||
@ -68,8 +67,8 @@ def config_variables(sender, **kwargs):
|
||||
name='pdf_fullscreen',
|
||||
default_value=False)
|
||||
|
||||
return ConfigPage(
|
||||
title='No title here', url='bar', required_permission=None, variables=(
|
||||
return ConfigCollection(
|
||||
required_permission=None, variables=(
|
||||
projector, projector_message,
|
||||
countdown_time, countdown_start_stamp, countdown_pause_stamp,
|
||||
countdown_state, projector_scale, projector_scroll,
|
||||
|
@ -277,7 +277,7 @@ class ConfigTest(TestCase):
|
||||
self.client = Client()
|
||||
self.client.login(username='config_test_admin', password='default')
|
||||
|
||||
def test_config_page_css_javascript(self):
|
||||
def test_config_collection_css_javascript(self):
|
||||
response = self.client.get('/config/agenda/')
|
||||
self.assertContains(response, 'timepicker.css', status_code=200)
|
||||
self.assertContains(response, 'jquery-ui-timepicker-addon.min.js', status_code=200)
|
||||
|
@ -7,8 +7,8 @@ from django.dispatch import receiver
|
||||
from django.test.client import Client
|
||||
from mock import patch
|
||||
|
||||
from openslides.config.api import (config, ConfigGroup, ConfigGroupedPage,
|
||||
ConfigPage, ConfigVariable)
|
||||
from openslides.config.api import (config, ConfigCollection, ConfigGroup,
|
||||
ConfigGroupedCollection, ConfigVariable)
|
||||
from openslides.config.exceptions import ConfigError, ConfigNotFound
|
||||
from openslides.config.signals import config_signal
|
||||
from openslides.participant.models import User
|
||||
@ -34,11 +34,11 @@ class HandleConfigTest(TestCase):
|
||||
callable_obj=self.get_config_var, key='unknown_config_var')
|
||||
|
||||
def test_get_multiple_config_var_error(self):
|
||||
config_signal.connect(set_simple_config_page_multiple_vars, dispatch_uid='set_simple_config_page_multiple_vars_for_testing')
|
||||
config_signal.connect(set_simple_config_view_multiple_vars, dispatch_uid='set_simple_config_view_multiple_vars_for_testing')
|
||||
self.assertRaisesMessage(expected_exception=ConfigError,
|
||||
expected_message='Too many values for config variable multiple_config_var found.',
|
||||
callable_obj=config.setup_cache)
|
||||
config_signal.disconnect(set_simple_config_page_multiple_vars, dispatch_uid='set_simple_config_page_multiple_vars_for_testing')
|
||||
config_signal.disconnect(set_simple_config_view_multiple_vars, dispatch_uid='set_simple_config_view_multiple_vars_for_testing')
|
||||
|
||||
def test_database_queries(self):
|
||||
"""
|
||||
@ -187,12 +187,50 @@ class ConfigFormTest(TestCase):
|
||||
{'integer_var': 'bad_string_value'})
|
||||
self.assertContains(response=response, text='errorlist', status_code=200)
|
||||
|
||||
def test_disabled_config_page(self):
|
||||
def test_disabled_config_view(self):
|
||||
response = self.client_manager.get('/config/testsimplepage3/')
|
||||
self.assertEqual(response.status_code, 404)
|
||||
response = self.client_manager.get('/config/testgroupedpage1/')
|
||||
self.assertNotContains(response=response, text='Ho5iengaoon5Hoht', status_code=200)
|
||||
|
||||
def test_improperly_configured_config_view(self):
|
||||
from openslides.config import urls
|
||||
collection = ConfigCollection(
|
||||
title='Only a small title but no url ci6xahb8Chula0Thesho',
|
||||
variables=(ConfigVariable(name='some_var_paiji9theiW8ooXivae6',
|
||||
default_value='',
|
||||
form_field=forms.CharField()),))
|
||||
|
||||
def setup_bad_config_view_one(sender, **kwargs):
|
||||
return collection
|
||||
|
||||
config_signal.connect(setup_bad_config_view_one, dispatch_uid='setup_bad_config_view_one_for_testing')
|
||||
self.assertRaisesMessage(
|
||||
ConfigError,
|
||||
'The config collection %s must have a title and an url attribute.' % repr(collection),
|
||||
reload,
|
||||
urls)
|
||||
config_signal.disconnect(setup_bad_config_view_one, dispatch_uid='setup_bad_config_view_one_for_testing')
|
||||
|
||||
def test_improperly_configured_config_view_two(self):
|
||||
from openslides.config import urls
|
||||
collection = ConfigCollection(
|
||||
url='only_url_ureiraeY1Oochuad7xei',
|
||||
variables=(ConfigVariable(name='some_var_vuuC6eiXeiyae3ik4gie',
|
||||
default_value='',
|
||||
form_field=forms.CharField()),))
|
||||
|
||||
def setup_bad_config_view_two(sender, **kwargs):
|
||||
return collection
|
||||
|
||||
config_signal.connect(setup_bad_config_view_two, dispatch_uid='setup_bad_config_view_twoe_for_testing')
|
||||
self.assertRaisesMessage(
|
||||
ConfigError,
|
||||
'The config collection %s must have a title and an url attribute.' % repr(collection),
|
||||
reload,
|
||||
urls)
|
||||
config_signal.disconnect(setup_bad_config_view_two, dispatch_uid='setup_bad_config_view_twoe_for_testing')
|
||||
|
||||
def test_extra_stylefiles(self):
|
||||
response = self.client_manager.get('/config/testgroupedpage1/')
|
||||
text = '<link href="/static/styles/test-config-sjNN56dFGDrg2.css" type="text/css" rel="stylesheet" />'
|
||||
@ -232,24 +270,24 @@ class ConfigWeightTest(TestCase):
|
||||
self.client_manager = Client()
|
||||
self.client_manager.login(username='config_test_manager', password='default')
|
||||
|
||||
def test_order_of_config_pages_abstract(self):
|
||||
config_page_dict = {}
|
||||
for receiver, config_page in config_signal.send(sender=self):
|
||||
config_page_dict[receiver.__name__] = config_page
|
||||
self.assertGreater(config_page_dict['set_grouped_config_page'].weight, config_page_dict['set_simple_config_page'].weight)
|
||||
def test_order_of_config_views_abstract(self):
|
||||
config_collection_dict = {}
|
||||
for receiver, config_collection in config_signal.send(sender=self):
|
||||
config_collection_dict[receiver.__name__] = config_collection
|
||||
self.assertGreater(config_collection_dict['set_grouped_config_view'].weight, config_collection_dict['set_simple_config_view'].weight)
|
||||
|
||||
def test_order_of_config_pages_on_view(self):
|
||||
def test_order_of_config_collections_on_view(self):
|
||||
response = self.client_manager.get('/config/testgroupedpage1/')
|
||||
import re
|
||||
m1 = re.search('<a href="/config/testgroupedpage1/" class="btn btn-mini active">Config vars for testing 1</a>', response.content)
|
||||
m2 = re.search('<a href="/config/testsimplepage1/" class="btn btn-mini ">Config vars for testing 2</a>', response.content)
|
||||
m1 = re.search('<a href="/config/testgroupedpage1/" class="btn btn-mini active">\s*Config vars for testing 1\s*</a>', response.content)
|
||||
m2 = re.search('<a href="/config/testsimplepage1/" class="btn btn-mini ">\s*Config vars for testing 2\s*</a>', response.content)
|
||||
self.assertGreater(m1.start(), m2.start())
|
||||
|
||||
|
||||
@receiver(config_signal, dispatch_uid='set_grouped_config_page_for_testing')
|
||||
def set_grouped_config_page(sender, **kwargs):
|
||||
@receiver(config_signal, dispatch_uid='set_grouped_config_view_for_testing')
|
||||
def set_grouped_config_view(sender, **kwargs):
|
||||
"""
|
||||
Sets a grouped config page which can be reached under the url
|
||||
Sets a grouped config collection view which can be reached under the url
|
||||
'/config/testgroupedpage1/'. There are some variables, one variable
|
||||
with a string as default value, one with a boolean as default value,
|
||||
one with an integer as default value, one with choices and one
|
||||
@ -278,7 +316,8 @@ def set_grouped_config_page(sender, **kwargs):
|
||||
form_field=forms.ChoiceField(choices=((1, 'Choice One Ughoch4ocoche6Ee'), (2, 'Choice Two Vahnoh5yalohv5Eb'))))
|
||||
group_2 = ConfigGroup(title='Group 2 Toongai7ahyahy7B', variables=(hidden_var, choices_var))
|
||||
|
||||
return ConfigGroupedPage(title='Config vars for testing 1',
|
||||
return ConfigGroupedCollection(
|
||||
title='Config vars for testing 1',
|
||||
url='testgroupedpage1',
|
||||
required_permission='config.can_manage',
|
||||
weight=10000,
|
||||
@ -287,13 +326,14 @@ def set_grouped_config_page(sender, **kwargs):
|
||||
'extra_javascript': ['javascript/test-config-djg4dFGVslk4209f.js']})
|
||||
|
||||
|
||||
@receiver(config_signal, dispatch_uid='set_simple_config_page_for_testing')
|
||||
def set_simple_config_page(sender, **kwargs):
|
||||
@receiver(config_signal, dispatch_uid='set_simple_config_view_for_testing')
|
||||
def set_simple_config_view(sender, **kwargs):
|
||||
"""
|
||||
Sets a simple config page with some config variables but without
|
||||
Sets a simple config view with some config variables but without
|
||||
grouping.
|
||||
"""
|
||||
return ConfigPage(title='Config vars for testing 2',
|
||||
return ConfigCollection(
|
||||
title='Config vars for testing 2',
|
||||
url='testsimplepage1',
|
||||
required_permission='No permission required',
|
||||
variables=(ConfigVariable(name='additional_config_var', default_value='BaeB0ahcMae3feem'),
|
||||
@ -302,30 +342,33 @@ def set_simple_config_page(sender, **kwargs):
|
||||
|
||||
|
||||
# Do not connect to the signal now but later inside the test.
|
||||
def set_simple_config_page_multiple_vars(sender, **kwargs):
|
||||
def set_simple_config_view_multiple_vars(sender, **kwargs):
|
||||
"""
|
||||
Sets a bad config page with some multiple config vars.
|
||||
Sets a bad config view with some multiple config vars.
|
||||
"""
|
||||
return ConfigPage(title='Config vars for testing 3',
|
||||
return ConfigCollection(
|
||||
title='Config vars for testing 3',
|
||||
url='testsimplepage2',
|
||||
required_permission='No permission required',
|
||||
variables=(ConfigVariable(name='multiple_config_var', default_value='foobar1'),
|
||||
ConfigVariable(name='multiple_config_var', default_value='foobar2')))
|
||||
|
||||
|
||||
@receiver(config_signal, dispatch_uid='set_simple_config_page_disabled_page_for_testing')
|
||||
def set_simple_config_page_disabled_page(sender, **kwargs):
|
||||
return ConfigPage(title='Ho5iengaoon5Hoht',
|
||||
@receiver(config_signal, dispatch_uid='set_simple_config_collection_disabled_view_for_testing')
|
||||
def set_simple_config_collection_disabled_view(sender, **kwargs):
|
||||
return ConfigCollection(
|
||||
title='Ho5iengaoon5Hoht',
|
||||
url='testsimplepage3',
|
||||
required_permission='No permission required',
|
||||
variables=(ConfigVariable(name='hidden_config_var_2', default_value=''),))
|
||||
|
||||
|
||||
@receiver(config_signal, dispatch_uid='set_simple_config_page_with_callback_for_testing')
|
||||
def set_simple_config_page_with_callback(sender, **kwargs):
|
||||
@receiver(config_signal, dispatch_uid='set_simple_config_collection_with_callback_for_testing')
|
||||
def set_simple_config_collection_with_callback(sender, **kwargs):
|
||||
def callback():
|
||||
raise Exception('Change callback dhcnfg34dlg06kdg successfully called.')
|
||||
return ConfigPage(title='Hvndfhsbgkridfgdfg',
|
||||
return ConfigCollection(
|
||||
title='Hvndfhsbgkridfgdfg',
|
||||
url='testsimplepage4',
|
||||
required_permission='No permission required',
|
||||
variables=(ConfigVariable(
|
||||
|
Loading…
Reference in New Issue
Block a user