diff --git a/.travis.yml b/.travis.yml index a051acc92..142b08c05 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,7 @@ script: - "isort --check-only --recursive openslides tests" - "DJANGO_SETTINGS_MODULE='tests.settings' coverage run ./manage.py test tests.unit" - - "coverage report --fail-under=42" + - "coverage report --fail-under=43" - "DJANGO_SETTINGS_MODULE='tests.settings' coverage run ./manage.py test tests.integration" - "coverage report --fail-under=50" diff --git a/openslides/agenda/projector.py b/openslides/agenda/projector.py index 13dac488c..c55356737 100644 --- a/openslides/agenda/projector.py +++ b/openslides/agenda/projector.py @@ -23,15 +23,10 @@ class ItemListSlide(ProjectorElement): def get_context(self): pk = self.config_entry.get('id') - if pk is None: - # Root list slide. - context = {'tree': self.config_entry.get('tree', False)} - else: + if pk is not None: # Children slide. if not Item.objects.filter(pk=pk).exists(): raise ProjectorException(_('Item does not exist.')) - context = {'id': pk, 'tree': self.config_entry.get('tree', False)} - return context def get_requirements(self, config_entry): pk = config_entry.get('id', 'tree') @@ -65,7 +60,6 @@ class ItemDetailSlide(ProjectorElement): raise ProjectorException(_('Id must not be None.')) if not Item.objects.filter(pk=pk).exists(): raise ProjectorException(_('Item does not exist.')) - return {'id': pk, 'list_of_speakers': self.config_entry.get('list_of_speakers', False)} def get_requirements(self, config_entry): pk = config_entry.get('id') diff --git a/openslides/agenda/static/js/agenda/agenda.js b/openslides/agenda/static/js/agenda/agenda.js index e9b33b1bb..36b40a59f 100644 --- a/openslides/agenda/static/js/agenda/agenda.js +++ b/openslides/agenda/static/js/agenda/agenda.js @@ -392,12 +392,12 @@ angular.module('OpenSlidesApp.agenda.projector', ['OpenSlidesApp.agenda']) // Attention! Each object that is used here has to be dealt on server side. // Add it to the coresponding get_requirements method of the ProjectorElement // class. - var id = $scope.element.context.id; + var id = $scope.element.id; Agenda.find(id); User.findAll(); Agenda.bindOne(id, $scope, 'item'); // get flag for list-of-speakers-slide (true/false) - $scope.is_list_of_speakers = $scope.element.context.list_of_speakers; + $scope.is_list_of_speakers = $scope.element.list_of_speakers; } ]) diff --git a/openslides/assignments/projector.py b/openslides/assignments/projector.py index 6687ed11d..205c559c3 100644 --- a/openslides/assignments/projector.py +++ b/openslides/assignments/projector.py @@ -18,15 +18,10 @@ class AssignmentSlide(ProjectorElement): def get_context(self): pk = self.config_entry.get('id') - if pk is None: - # List slide. - context = None - else: + if pk is not None: # Detail slide. if not Assignment.objects.filter(pk=pk).exists(): raise ProjectorException(_('Assignment does not exist.')) - context = {'id': pk} - return context def get_requirements(self, config_entry): pk = config_entry.get('id') diff --git a/openslides/assignments/static/js/assignments/assignments.js b/openslides/assignments/static/js/assignments/assignments.js index c9f4ced1d..cd179a984 100644 --- a/openslides/assignments/static/js/assignments/assignments.js +++ b/openslides/assignments/static/js/assignments/assignments.js @@ -131,7 +131,7 @@ angular.module('OpenSlidesApp.assignments.projector', ['OpenSlidesApp.assignment // Attention! Each object that is used here has to be dealt on server side. // Add it to the coresponding get_requirements method of the ProjectorElement // class. - var id = $scope.element.context.id; + var id = $scope.element.id; Assignment.find(id); Assignment.bindOne(id, $scope, 'assignment'); }); diff --git a/openslides/core/models.py b/openslides/core/models.py index 09bbade37..bc3864d63 100644 --- a/openslides/core/models.py +++ b/openslides/core/models.py @@ -68,7 +68,8 @@ class Projector(RESTModelMixin, models.Model): # Parse result result = {} for key, value in self.config.items(): - result[key] = value + # Use a copy here not to change the origin value in the config field. + result[key] = value.copy() element = elements.get(value['name']) if element is None: result[key]['error'] = _('Projector element does not exist.') diff --git a/openslides/core/projector.py b/openslides/core/projector.py index 58ebe4088..ef1d7b1a0 100644 --- a/openslides/core/projector.py +++ b/openslides/core/projector.py @@ -16,10 +16,8 @@ class CustomSlideSlide(ProjectorElement): name = 'core/customslide' def get_context(self): - pk = self.config_entry.get('id') - if not CustomSlide.objects.filter(pk=pk).exists(): + if not CustomSlide.objects.filter(pk=self.config_entry.get('id')).exists(): raise ProjectorException(_('Custom slide does not exist.')) - return {'id': pk} def get_requirements(self, config_entry): pk = config_entry.get('id') diff --git a/openslides/core/serializers.py b/openslides/core/serializers.py index 7fb6db583..d541d6cbe 100644 --- a/openslides/core/serializers.py +++ b/openslides/core/serializers.py @@ -9,30 +9,28 @@ class JSONSerializerField(Field): """ def to_internal_value(self, data): """ - Checks that data is a list of dictionaries. Every dictionary must have - a key 'name'. + Checks that data is a dictionary. The key is a hex UUID and the + value is a dictionary with must have a key 'name'. """ - if type(data) is not list: - raise ValidationError('Data must be a list of dictionaries.') - for element in data: + if type(data) is not dict: + raise ValidationError('Data must be a dictionary.') + for element in data.values(): if type(element) is not dict: - raise ValidationError('Data must be a list of dictionaries.') + raise ValidationError('Data must be a dictionary.') elif element.get('name') is None: raise ValidationError("Every dictionary must have a key 'name'.") return data - def to_representation(self, value): - return value - class ProjectorSerializer(ModelSerializer): """ Serializer for core.models.Projector objects. """ + config = JSONSerializerField(write_only=True) class Meta: model = Projector - fields = ('id', 'elements', ) + fields = ('id', 'config', 'elements', ) class CustomSlideSerializer(ModelSerializer): diff --git a/openslides/core/static/js/core/core.js b/openslides/core/static/js/core/core.js index df7f58d7a..d9d08010c 100644 --- a/openslides/core/static/js/core/core.js +++ b/openslides/core/static/js/core/core.js @@ -765,7 +765,7 @@ angular.module('OpenSlidesApp.core.projector', ['OpenSlidesApp.core']) // Attention! Each object that is used here has to be dealt on server side. // Add it to the coresponding get_requirements method of the ProjectorElement // class. - var id = $scope.element.context.id; + var id = $scope.element.id; Customslide.find(id); Customslide.bindOne(id, $scope, 'customslide'); }) diff --git a/openslides/motions/projector.py b/openslides/motions/projector.py index 656ecea61..04b5a12a7 100644 --- a/openslides/motions/projector.py +++ b/openslides/motions/projector.py @@ -18,15 +18,10 @@ class MotionSlide(ProjectorElement): def get_context(self): pk = self.config_entry.get('id') - if pk is None: - # List slide. - context = None - else: + if pk is not None: # Detail slide. if not Motion.objects.filter(pk=pk).exists(): raise ProjectorException(_('Motion does not exist.')) - context = {'id': pk} - return context def get_requirements(self, config_entry): pk = config_entry.get('id') diff --git a/openslides/motions/static/js/motions/motions.js b/openslides/motions/static/js/motions/motions.js index e6fc8711d..a9c612596 100644 --- a/openslides/motions/static/js/motions/motions.js +++ b/openslides/motions/static/js/motions/motions.js @@ -348,7 +348,7 @@ angular.module('OpenSlidesApp.motions.projector', ['OpenSlidesApp.motions']) // Attention! Each object that is used here has to be dealt on server side. // Add it to the coresponding get_requirements method of the ProjectorElement // class. - var id = $scope.element.context.id; + var id = $scope.element.id; Motion.find(id); Motion.bindOne(id, $scope, 'motion'); }); diff --git a/openslides/users/projector.py b/openslides/users/projector.py index 5360dd469..2ec339477 100644 --- a/openslides/users/projector.py +++ b/openslides/users/projector.py @@ -14,10 +14,8 @@ class UserSlide(ProjectorElement): name = 'users/user' def get_context(self): - pk = self.config_entry.get('id') - if not User.objects.filter(pk=pk).exists(): + if not User.objects.filter(pk=self.config_entry.get('id')).exists(): raise ProjectorException(_('User does not exist.')) - return {'id': pk} def get_requirements(self, config_entry): pk = config_entry.get('id') diff --git a/openslides/users/static/js/users/users.js b/openslides/users/static/js/users/users.js index 32bfbe85a..af2aa45e6 100644 --- a/openslides/users/static/js/users/users.js +++ b/openslides/users/static/js/users/users.js @@ -547,7 +547,7 @@ angular.module('OpenSlidesApp.users.projector', ['OpenSlidesApp.users']) // Attention! Each object that is used here has to be dealt on server side. // Add it to the coresponding get_requirements method of the ProjectorElement // class. - var id = $scope.element.context.id; + var id = $scope.element.id; User.find(id); User.bindOne(id, $scope, 'user'); }); diff --git a/tests/integration/core/test_views.py b/tests/integration/core/test_views.py index 4cb5d08f0..bd95f2b50 100644 --- a/tests/integration/core/test_views.py +++ b/tests/integration/core/test_views.py @@ -34,7 +34,7 @@ class ProjectorAPI(TestCase): 'aae4a07b26534cfb9af4232f361dce73': {'id': customslide.id, 'name': 'core/customslide', - 'context': {'id': customslide.id}}}}) + 'context': None}}}) def test_invalid_slide_on_default_projector(self): self.client.login(username='admin', password='admin') diff --git a/tests/unit/core/test_views.py b/tests/unit/core/test_views.py index bb17cd082..7012b4d91 100644 --- a/tests/unit/core/test_views.py +++ b/tests/unit/core/test_views.py @@ -86,8 +86,7 @@ class ProjectorAPI(TestCase): 'test_key_mud1shoo8moh6eiXoong': 'test_value_shugieJier6agh1Ehie3'}] self.viewset.request = request self.viewset.prune_elements(request=request, pk=MagicMock()) - # TODO: Do not know how to test this. - # self.assertEqual(len(mock_object.return_value.config), 2) + self.assertEqual(len(mock_object.return_value.config), 2) def test_update_elements(self, mock_object): mock_object.return_value.config = { @@ -170,8 +169,7 @@ class ProjectorAPI(TestCase): request = MagicMock() self.viewset.request = request self.viewset.clear_elements(request=request, pk=MagicMock()) - # TODO: Do not know how to test this. - # self.assertEqual(len(mock_object.return_value.config), 0) + self.assertEqual(len(mock_object.return_value.config), 0) def test_clear_elements_with_stable(self, mock_object): mock_object.return_value.config = {